<!DOCTYPE html>
<html>
  <head>
    <meta content="text/html; charset=UTF-8" http-equiv="content-type">
    <title>ch03-04</title>
    <link href="css/style.css" rel="stylesheet" type="text/css">
    <link rel="stylesheet" href="thumbnailviewer.css" type="text/css">
    <script src="thumbnailviewer.js" type="text/javascript">

/***********************************************
* Image Thumbnail Viewer Script- © Dynamic Drive (www.dynamicdrive.com)
* This notice must stay intact for legal use.
* Visit http://www.dynamicdrive.com/ for full source code
***********************************************/

</script> </head>
  <body>
    <div class="os1">3.4 PortAudio指定时间片采集 </div>
    <br>
    本节主要介绍利用 PortAudio 进行指定时间片的音频采集，这对 OPUS 等要求输入数据时间片范围的音频编码非常有用。QAudioInput
    的采样时间片是内部计算的，一般无法掌控，所以需要介绍 PortAudio 开发库，方便以后与各种音频编码库对接。本节先介绍 PortAudio
    概览，然后介绍该库两套接口：基于 Pa_OpenDefaultStream() 简单接口和稍微复杂的基于 Pa_OpenStream()
    的接口，每套接口配备一个示例。 <br>
    &nbsp;<br>
    <div class="os2">3.4.1 PortAudio 概览 </div>
    <br>
    PortAudio 是开源的跨平台的音频 I/O 库，专门用于播放和采集原始音频数据，它的编程接口非常简单，适用于 C 和 C++
    跨平台开发，另外还有对应的 Python 绑定模块 PyAudio ，可以运行在 Windows、Max OS X、Unix、Linux
    等各种系统平台。PortAudio 提供了基于回调函数的采集模式和阻塞式读写接口，通常建议使用回调函数，本节也只介绍使用回调函数的方式采集音频数据。<br>
    <br>
    PortAudio 支持多种底层音频I/O框架，比如在 Windows 支持 WMME（Windows MultiMedia Extension，即
    Windows Multimedia API）、DirectX（DirectSound）、WDM/KS、ASIO、WASAPI
    等，各系统详细情况见下图：<br>
    <br>
    <center> <img src="images/ch03/portaudioarch.png" alt="portaudio" width="800">
    </center>
    <br>
    PortAudio 在各个系统平台的 API 接口函数是统一的，虽然 API
    函数名称一致，但是各个系统平台的实现功能有可能存在差异。如果操作系统底层音频框架（PortAudio 称之为 Host
    APIs）和声卡设备（Devices）不支持某些功能，那么 PortAudio 的相应功能就受限。比如声卡不支持 192kHz 频率的音频采集，那么
    PortAudio 也就不能提供 192kHz 采样数据。在底层音频框架和设备支持的情况下，PortAudio 可以很方便地指定时间片来进行音频采集。<br>
    <br>
    PortAudio
    采集过程基于流（Streams），如果底层支持，那么一个流对象可以同时打开输入流和输出流，但是一般建议一个流对象只处理输入流或者只处理输出流。音频输入输出方
    式（ I/O Methods ）可以采用异步的回调函数方式，也可以采用同步的阻塞函数方式，当然通常都是用回调函数实现数据采集或播放。 <br>
    <br>
    PortAudio 官方网站：<br>
    <a href="http://www.portaudio.com/" target="new">http://www.portaudio.com/</a><br>
    PortAudio 详细文档：<br>
    <a href="http://portaudio.com/docs/v19-doxydocs/" target="new">
      http://portaudio.com/docs/v19-doxydocs/</a><br>
    可以从 PortAudio 官方网站下载源代码包编译安装，作者使用 MinGW32 编译好了一份 PortAudio 开发库：<br>
    <a href="https://gitee.com/qtguide/oscodec/tree/master/libs" target="new">
      https://gitee.com/qtguide/oscodec/tree/master/libs </a> <br>
    读者下载 portaudio_v190600_mingw32.zip 后解压该压缩包，进入 portaudio_v190600_mingw32
    文件夹，然后复制里面的所有内容（bin、i686-w64-mingw32、include、lib 四个子文件夹），粘贴到 MinGW 路径：<br>
    <b>C:\Qt\Qt5.4.0\Tools\mingw491_32</b><br>
    注意四个子文件夹与 MinGW 路径内的子文件夹是对应的，粘贴时选择文件夹复制合并。<br>
    <br>
    <div class="os2">3.4.2 PortAudio 简单接口及采集示例</div>
    <br>
    PortAudio 简单接口是基于 Pa_OpenDefaultStream()
    函数，不关心底层的音频框架和设备，都用默认的输入输出设备和音频框架，只需要设置通道数量、采样点格式、采样频率、时间片内帧数、回调函数等即可。使用回调函数
    的操作流程如下：<br>
    <ol>
      <li>编写回调函数，PortAudio 会周期地调用该函数，反馈采集到的音频数据或从该函数获取音频数据播放到声卡。 </li>
      <li>初始化 PortAudio，打开一个音频输入或输出的流。 </li>
      <li>开始音频流，回调函数会被 PortAudio 库在后台自动地重复调用，进行音频采集或音频播放。 </li>
      <li>在回调函数读取 PortAudio 库采集的数据 inputBuffer ，或者构造输出数据 outputBuffer 提供给 PortAudio 库用于播放。 </li>
      <li>停止流：在回调函数返回 1 可以自动停止流，或者手动调用停止流的函数。 </li>
      <li>关闭流，终止库的使用。 </li>
    </ol>
    不论是简单接口还是复杂接口，基于回调函数机制的流程都是类似的，复杂接口可以设置具体的底层音频框架和设备，而简单接口则不关心底层的音频框架和设 备。<br>
    下面我们分步骤讲解 PortAudio 简单接口的使用：<br>
    （1）回调函数编写<br>
    PortAudio 库（以下简称 PA 库）规定了回调函数的格式，函数名可以自己定义，参数和返回值类型必须如下面示例的一样：<br>
    <div class="code">typedef int PaStreamCallback( const void *inputBuffer,<br>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
      void *outputBuffer,<br>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
      unsigned long frameCount,<br>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
      const PaStreamCallbackTimeInfo* timeInfo,<br>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
      PaStreamCallbackFlags statusFlags,<br>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
      void *userData ) ;</div>
    回调函数必须是全局函数，不能是 C++ 类的成员函数，因为类成员函数一般需要隐藏的 this 指针。<br>
    该函数的返回值用于确定是否继续重复调用回调函数，可用的返回值列表如下：<br>
    <br>
    <table class="tabel">
      <tbody>
        <tr class="d1">
          <td style="width: 280px;" align="center"><b>PaStreamCallbackResult
              枚举常量</b></td>
          <td style="width: 100px;" align="center"><b>数值</b></td>
          <td align="center"><b> 描述</b></td>
        </tr>
        <tr>
          <td>paContinue</td>
          <td> 0</td>
          <td> 通知继续音频流，继续重复调用回调函数。 </td>
        </tr>
        <tr class="d1">
          <td>paComplete</td>
          <td> 1</td>
          <td> 通知停止音频流，当本次缓冲区数据输出完成后停止流。 </td>
        </tr>
        <tr>
          <td>paAbort </td>
          <td> 2</td>
          <td> 通知中断音频流，不管缓冲区有没有数据，立即停止流。 </td>
        </tr>
      </tbody>
    </table>
    <br>
    注意回调函数里面一定要写清楚返回值，如果没有返回值，音频流也会自动停止。<br>
    回调函数的参数有 6 个：<br>
    ① inputBuffer 用于音频输入，是 PA 库从声卡采集的音频输入数据缓冲区指针，可以强制类型转化为需要的数据格式指针。<br>
    ② outputBuffer 用于音频输出，可以自己构造输出数据填充到该缓冲区，缓冲区的空间都是 PA
    库自动分配，程序员只需要读写缓冲区，而不管分配和释 放。<br>
    <br>
    默认情况下，多个声道都是交错式存储，输入或输出数据指针仅指向各自的一个数据缓冲区。<br>
    但是，如果在打开流时设置了 paNonInterleaved 数据格式标志位，那么 inputBuffer / outputBuffer
    是一个指针数组，指针数组里元素个数等于声道数，各个元素指向各个声道的缓冲区。比如双声道输入时，inputBuffer[0]
    指向左声道数据缓冲区，inputBuffer[1] 指向右声道数据缓冲区。 <br>
    &nbsp;<br>
    ③ frameCount 是指在时间片内采集的帧数或者期望播放的帧数，帧数与时间片有运算关系，frameCount / sampleRate ==
    采样时间片，音频输入或输出的缓冲区大小刚好容纳时间片内的所有帧数据。<br>
    ④ timeInfo 用于记录当前缓冲区时间片在整个音频流中的时间位置，timeInfo 包括三个成员：currentTime
    记录调用该回调函数的时刻，inputBufferAdcTime 记录当前输入缓冲区头一帧在 A/D
    转换器输入流中的时刻，outputBufferDacTime 记录当前输出缓冲区头一帧在 D/A 转换器输出流中的时刻。<br>
    ⑤ statusFlags 表示回调函数的数据供给状态，比如时间片内写入的数据太多还是太少，具体的状态标志如下表所示：<br>
    <br>
    <table class="tabel">
      <tbody>
        <tr class="d1">
          <td align="center"><b>PaStreamCallbackFlags 状态标志位<br>
            </b></td>
          <td align="center"><b>数值</b></td>
          <td align="center"><b> 描述</b></td>
        </tr>
        <tr>
          <td>paInputUnderflow</td>
          <td> 0x00000001</td>
          <td> 输入数据不足。<br>
            如果打开流时采用了 paFramesPerBufferUnspecified 模式，说明输入数据全是 0，没有采集到任何真实数据。<br>
            如果打开流时没有用 paFramesPerBufferUnspecified，表明输入数据末尾插入了一个或多个 0
            值样本点，以补偿输入数据不足。<br>
          </td>
        </tr>
        <tr class="d1">
          <td>paInputOverflow </td>
          <td> 0x00000002</td>
          <td> 输入数据过多。<br>
            如果打开流时采用了 paFramesPerBufferUnspecified
            模式，说明缓冲区头一帧之前的输入数据由于过载被抛弃了，可能由于回调函数占用太多 CPU 时间导致数据丢弃。<br>
            其他情况下，说明输入缓冲区头一帧之前的样本数据被丢弃。<br>
          </td>
        </tr>
        <tr>
          <td>paOutputUnderflow</td>
          <td> 0x00000004</td>
          <td style="height: 45px;"> 输出数据不足。<br>
            说明输出数据已经插入到输出流，但是输出数据不足，存在一段时间空白，有可能是占用 CPU 时间过多导致。 </td>
        </tr>
        <tr class="d1">
          <td>paOutputOverflow</td>
          <td> 0x00000008</td>
          <td style="height: 30px;"> 输出数据过多。<br>
            输出数据会被丢弃，因为输出流的缓存没空间容纳新数据。<br>
          </td>
        </tr>
        <tr>
          <td style="width: 280px;">paPrimingOutput </td>
          <td style="width: 100px;"> 0x00000010</td>
          <td> 正在装填输出数据，还没正式播放，输入数据可能是 0。 </td>
        </tr>
      </tbody>
    </table>
    <br>
    如果状态值 statusFlags 保持为 0，说明没有数据不足或过多的问题。<br>
    ⑥ userData 是用户自定义的数据，可以是任意值，用户在打开流时设置用户数据指针，然后 PA
    库原封不动地传递给回调函数。可以方便传递音频格式信息或者 C++ 对象的 this 指针给回调函数。<b>因为回调函数必须是全局函数，不能是 类的成员函
      数。</b>类 的成员函数一般都有隐藏的 this 指针参数，而 C 语言没有这些东西。如果不需要使用自定义的用户数据，那么在打开流时可以设置
    userData 为 NULL 。<br>
    <br>
    回调函数的编写有一个基本要求：<b>回调函数内代码要尽可能快速地执行完，避免在回调函数内执行耗时长的函数。</b><br>
    因为回调函数通常以几十毫秒的时间片重复执行，如果回调函数内代码执行耗费的时间超过指定时间片，音频输入输出就会卡顿，音频数据存在丢失，那样声音 就不流
    畅，可能导致声音听不到、采不全。尽量避免的操作有：内存分配、释放，文件输入输出、控制台输入输出、阻塞式网络输入输出，运行环境切换（比如
    exec()、yield()），互斥量操作，其他等待耗时操作等。另外，在回调函数内不要调用 PA
    库的函数，这样做不安全，除非该函数特别说明可以在回调函数内使用。<br>
    <br>
    本小节的示例会编写一个简单的回调函数，将采集到的音频数据写入到文件和网络套接字，Qt 的文件类带有输入输出缓存，耗费时间短，可以放在回调函数内执行；Qt
    的网络套接字一般用异步接口，不使用同步接口就可以放在回调函数内执行。实测该回调函数一次执行耗时大概 0.1 ms 左右，不会干扰采集的流畅性。<br>
    <br>
    （2）初始化 PA 库<br>
    <div class="code">PaError&nbsp; err = Pa_Initialize();<br>
      if( err != paNoError ) <br>
      &nbsp;&nbsp;&nbsp; printf(&nbsp; "PortAudio error: %s\n", Pa_GetErrorText(
      err ) );</div>
    使用 Pa_Initialize() 初始化 PA 库，返回值如果不是 paNoError ，那么初始化失败，打印错误信息。<br>
    <br>
    （3）使用默认底层音频框架和设备打开音频流<br>
    PA 使用流句柄表示一个音频流：
    <div class="code">PaStream *stream;</div>
    PaStream 其实就是 void 空类型，stream 就是一个指针变量，表示流的句柄。<br>
    简单接口基于 Pa_OpenDefaultStream() 函数，其声明如下：<br>
    <div class="code">PaError Pa_OpenDefaultStream( PaStream **
      &nbsp;&nbsp;&nbsp; pstream,<br>
      int &nbsp;&nbsp; &nbsp;numInputChannels,<br>
      int &nbsp;&nbsp; &nbsp;numOutputChannels,<br>
      PaSampleFormat &nbsp;&nbsp; &nbsp;sampleFormat,<br>
      double &nbsp;&nbsp; &nbsp;sampleRate,<br>
      unsigned long &nbsp;&nbsp; &nbsp;framesPerBuffer,<br>
      PaStreamCallback * &nbsp;&nbsp; &nbsp;streamCallback,<br>
      void * &nbsp;&nbsp; &nbsp;userData <br>
      )&nbsp;&nbsp;&nbsp; </div>
    该函数返回值是 PaError 类型，如果返回值不等于 paNoError 说明打开错误，可以用 Pa_GetErrorText( err )
    获取错误信息字符串。<br>
    该函数的 8 个参数意义如下：<br>
    ① pstream 是指向流句柄的指针，即 &amp;stream 的数值，该函数会创建流句柄，分配流所需的资源。<br>
    ② numInputChannels 指打开输入声道数量。<br>
    ③ numOutputChannels 指打开输出声道数量，一般只设置输入声道或只设置输出声道，另一个不使用的设置为 0 。<br>
    ④ sampleFormat 是采样点数据格式，具体如下表所示：<br>
    <br>
    <table class="tabel">
      <tbody>
        <tr class="d1">
          <td style="width: 280px;" align="center"><b>PaSampleFormat 枚举常量</b></td>
          <td style="width: 100px;" align="center"><b>数值</b></td>
          <td align="center"><b> 描述</b></td>
        </tr>
        <tr>
          <td>paFloat32 </td>
          <td> 0x00000001</td>
          <td> 32位浮点数采样，取值 -1.0 ~ +1.0。 </td>
        </tr>
        <tr class="d1">
          <td>paInt32</td>
          <td> 0x00000002</td>
          <td> 32位有符号整数。 </td>
        </tr>
        <tr>
          <td>paInt24 </td>
          <td> 0x00000004</td>
          <td> 24位有符号整数。 </td>
        </tr>
        <tr class="d1">
          <td>paInt16</td>
          <td> 0x00000008</td>
          <td> 16位有符号整数。 </td>
        </tr>
        <tr>
          <td>paInt8 </td>
          <td> 0x00000010</td>
          <td> 8位有符号整数。 </td>
        </tr>
        <tr class="d1">
          <td>paUInt8</td>
          <td> 0x00000020</td>
          <td> 8位无符号整数，数值128表示地板值（静音）。 </td>
        </tr>
        <tr>
          <td> paCustomFormat</td>
          <td> 0x00010000</td>
          <td> 自定义数据格式。 </td>
        </tr>
        <tr class="d1">
          <td>paNonInterleaved</td>
          <td> 0x80000000</td>
          <td> 非交错存储格式。 </td>
        </tr>
      </tbody>
    </table>
    <br>
    从 32 位到 8 位是标准采样点格式，一般都是受音频框架和设备支持的。paCustomFormat 用不到，预留的。<br>
    paNonInterleaved 标志位可以与其他格式同时使用，表示使用非交错的数据存储格式。<br>
    如果不设置该标志位，默认都是交错存储格式，以双声道为例，交错存储序列为：<br>
    左，右，左，右，左，右……<br>
    如果设置了 paNonInterleaved 标志位，那么使用非交错存储格式：<br>
    buffer[0] 是一个指针，指向左声道的数据缓冲区：左，左，左……，<br>
    buffer[1] 是一个指针，指向右声道的数据缓冲区：右，右，右……<br>
    <br>
    ⑤ sampleRate，采样频率，单位是 Hz，输入输出声道使用同一个采样频率。<br>
    ⑥ framesPerBuffer，缓冲区内帧数，即采样时间片内的帧数，framesPerBuffer/sampleRate
    就是采样时间片。如果设置该参数为 paFramesPerBufferUnspecified（数值 0 ），PA 库会自动设置缓冲区帧数和采样时间片。<br>
    ⑦ streamCallback，回调函数名称。<br>
    ⑧ userData ，用户数据指针，该指针会原封不动地传递给回调函数，也就是回调函数最后一个参数值。<br>
    <br>
    虽然 Pa_OpenDefaultStream()
    函数接口同时带有音频输入和输出的声道数，但是底层音频框架和设备不一定同时支持打开音频输入、输出，所以建议一个音频流句柄只管理输入或只管理输出，输入流和输
    出流一般分开使用。<br>
    <br>
    （4）开始、停止和中断音频流<br>
    Pa_OpenDefaultStream() 仅仅是准备工作，真正开始数据采集或播放 使用下面函数：<br>
    <div class="code">PaError Pa_StartStream( PaStream * stream ) </div>
    参数就是流句柄，返回值是 PaError 类型，返回值意义同之前函数类似。音频流开始之后，PA 库就会自动调用回调函数，进行音频采集或播放，回调函数内部
    一般返回 0，就是自动继续音频流。<br>
    停止音频流的函数如下：<br>
    <div class="code">PaError Pa_StopStream( PaStream * stream )</div>
    这个函数会等待音频输出缓存处理完成之后，停止音频流。<br>
    如果希望立即中断音频流，不管缓冲区数据有没有处理都停止流，使用下面函数：<br>
    <div class="code">PaError Pa_AbortStream( PaStream * stream )</div>
    <br>
    （5）关闭流并终止库使用<br>
    当流使用完成之后，调用下面函数关闭流，释放流占用的资源：<br>
    <div class="code">PaError Pa_CloseStream( PaStream * stream )</div>
    当不再使用 PA 库的时候，释放库引用使用下面函数：<br>
    <div class="code">PaError Pa_Terminate(void)</div>
    一般 Pa_Terminate() 在程序结束之前调用（比如主窗口析构函数），而初始化函数 Pa_Initialize()
    放在程序开始的位置调用（比如主窗口的构造函数）。<br>
    <br>
    顺便提一下，判断音频流的工作状态函数有两个，第一个判断流是否停止：<br>
    <div class="code">PaError Pa_IsStreamStopped( PaStream *stream )</div>
    对之前正常工作的音频流调用 Pa_StopStream() 或者 Pa_AbortStream() 之后，流状态定义为停止状态，该函数返回 1；<br>
    当流正在工作或者从回调函数返回 非 paContinue 数值（回调函数不再被调用，但也不视为停止状态），那么函数返回
    0，其他出错或者没有初始化时的情况，返回负数，即错误代码。<br>
    第二个函数判断流是否处在活跃的工作状态：<br>
    <div class="code">PaError Pa_IsStreamActive( PaStream *stream )</div>
    当音频流正在采集或播放时，该函数返回 1；<br>
    如果 Pa_StopStream() 或 Pa_AbortStream() 导致流停止，或者在回调函数返回 非paContinue 数值停止流，那么返回
    0，表示流不活跃；如果出错或者没初始化，返回负数，即错误代码。<br>
    <br>
    获取当前时间的函数为：<br>
    <div class="code">PaTime Pa_GetStreamTime(PaStream * stream)</div>
    PaTime 就是 double 类型，表示时间的秒数，该函数获取的时间可能是以系统时钟或开机时钟为准，一般不从 0
    开始计时。不管流开始还是结束，这个时钟一直不停地在走，获取流开始和流结束两个时间点的差值可以大致计算流实际的工作时长。<br>
    <br>
    对于 PortAudio 简单接口只需要了解上面这些内容，开始示例之前，我们先说明一下，作者使用 MinGW32 编译好的 PortAudio
    开发库，仅支持 WMME 和 DirectSound 底层音频框架，其他音频框架需要使用 VC 编译器，这里就不考虑其他音频框架了，因为我们使用
    MinGW 编译套件。<br>
    下面我们打开 QtCreator，新建一个 Qt Widgets Application 项目，在新建项目的向导里填写：<br>
    ①项目名称 <b>painsimple</b>，创建路径 E:\examples\ch03，点击下一步；<br>
    ②套件选择里面选择全部套件，点击下一步；<br>
    ③类信息界面先选择基类为 <b>QWidget</b>，修改类名为 <b>WidgetPAInSimple</b>，点击下一步；<br>
    ④项目管理不修改，点击完成。<br>
    我们先打开 painsimple.pro 文件，为项目添加 Qt 网络模块，并增加 PA 库的引用 ：<br>
    <div class="code">#-------------------------------------------------<br>
      #<br>
      # Project created by QtCreator 2018-11-24T10:06:01<br>
      #<br>
      #-------------------------------------------------<br>
      <br>
      QT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; += core gui <b>network</b><br>
      <br>
      greaterThan(QT_MAJOR_VERSION, 4): QT += widgets<br>
      <br>
      TARGET = painsimple<br>
      TEMPLATE = app<br>
      <br>
      <br>
      SOURCES += main.cpp\<br>
      &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; widgetpainsimple.cpp<br>
      <br>
      HEADERS&nbsp; += widgetpainsimple.h<br>
      <br>
      FORMS&nbsp;&nbsp;&nbsp; += widgetpainsimple.ui<br>
      <br>
      <b>LIBS += -lportaudio</b></div>
    因为我们的 portaudio 库安装在 MinGW 标准库路径，所以直接加一句：<br>
    LIBS += -lportaudio<br>
    不需要指定 portaudio 库的路径位置，MinGW 自己就能找到 portaudio 头文件和库文件。<br>
    编辑 pro 文件之后，保存该文件，关闭该文件，打开 widgetpainsimple.ui 界面文件，按照下图拖入控件：<br>
    <center> <img src="images/ch03/ch03-04-01.png" alt="ui" width="800"> <br>
    </center>
    界面第一行：标签“输入声道数量”、组合框 comboBoxChannels、标签“采样位宽”、组合框 comboBoxSampleSize；<br>
    第二行：标签“采样频率”、组合框 comboBoxSampleRate、标签“时间片帧数”、旋钮编辑框 spinBoxFramesPerBuffer，<br>
    第一行和第二行控件使用一个栅格布局排布。<br>
    第三行：标签“目标地址”、单行编辑器 lineEditIP、标签“目标端口”、旋钮编辑框 spinBoxPort，第三行使用水平布局器排布。<br>
    第四行：标签“文件路径”、单行编辑器 lineEditFile，第四行使用水平布局器排布。<br>
    第五行是两个按钮，“开始”按钮 pushButtonStart、“停止”按钮 pushButtonStop，第五行也用水平布局器排布。<br>
    第六行是标签控件，初始文本“采集状态”，修改标签的对象名为 labelStatus。<br>
    窗口整体使用垂直布局器排布，窗口大小 340*200。<br>
    界面排布完成后，依次右键点击两个按钮，从右键菜单为按钮添加槽函数：<br>
    <center> <img src="images/slots/buttonclicked.png" alt="slot"> <br>
    </center>
    两个按钮槽函数添加完成后，保存界面文件，关闭界面文件。<br>
    打开头文件 widgetpainsimple.h ，编辑该文件内容：<br>
    <div class="code"><span style=" color:#000080;">#ifndef</span><span style=" color:#c0c0c0;">
      </span>WIDGETPAINSIMPLE_H
      <pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#define</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">WIDGETPAINSIMPLE_H</span></pre>
      <pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;QWidget&gt;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;portaudio.h&gt;//</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">PortAudio开发库</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;QFile&gt;</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">//文件</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;QUdpSocket&gt;//UDP套接字</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;QHostAddress&gt;</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">//IP地址类</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;QElapsedTimer&gt;</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">//计时器类</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">namespace</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">Ui</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">class</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">WidgetPAInSimple</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#008000;">//自定义回调函数声明</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">static</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">audioInCallback</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">const</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">void</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">*</span>inputBuffer<span style=" color:#000000;">,</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                     </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span>outputBuffer<span
style=" color:#000000;">,</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                     </span><span style=" color:#808000;">unsigned</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">long</span><span style=" color:#c0c0c0;"> </span>frameCount<span
style=" color:#000000;">,</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                     </span><span style=" color:#808000;">const</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">PaStreamCallbackTimeInfo</span><span
style=" color:#000000;">*</span><span style=" color:#c0c0c0;"> </span>timeInfo<span
style=" color:#000000;">,</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                     </span><span style=" color:#800080;">PaStreamCallbackFlags</span><span
style=" color:#c0c0c0;"> </span>statusFlags<span style=" color:#000000;">,</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                     </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span>userData<span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">)</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">;</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">class</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">WidgetPAInSimple</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">:</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">public</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QWidget</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000080;">Q_OBJECT</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">public</span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">explicit</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">WidgetPAInSimple</span><span
style=" color:#000000;">(</span><span style=" color:#800080;">QWidget</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span>parent<span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">0</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">~</span><span style=" font-style:italic; color:#000000;">WidgetPAInSimple</span><span
style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//声明公开变量，方便回调函数访问</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//音频流</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">PaStream</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span><span style=" color:#800000;">m_streamIn</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//输入声道数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_nChannels</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//采样位宽，单位比特</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_nSampleSize</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//采样频率</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_nSampleRate</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//时间片内帧数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_nFramesPerBuffer</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//套接字</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QUdpSocket</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_socket</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//文件</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QFile</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_file</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//计时器</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QElapsedTimer</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_calcTime</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//状态显示函数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">showStatus</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span>nFrames<span
style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span>nBytes<span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//根据采样位宽获取采样点数据格式</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">PaSampleFormat</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">getSampleFormat</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span>sampleSize<span
style=" color:#000000;">);</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">private</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#808000;">slots</span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">on_pushButtonStart_clicked</span><span
style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">on_pushButtonStop_clicked</span><span
style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">private</span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">Ui</span><span
style=" color:#000000;">::</span><span style=" color:#800080;">WidgetPAInSimple</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//界面初始化</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">initUI</span><span
style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//录音时固定参数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">holdParas</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">bool</span><span
style=" color:#c0c0c0;"> </span>bHold<span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">};</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#endif</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">//</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">WIDGETPAINSIMPLE_H</span></pre>
</div>
    
    该文件添加了 PA 库的头文件引用，还有 Qt 的文件、UDP套接字、IP地址类、计时器类头文件引用。<br>在窗口类声明之前，手动添加了回调函数 audioInCallback() 声明，用于重复获取音频采样数据。<br>窗口类的声明中，手动添加了各个公有成员变量，因为回调函数是全局函数，使用公有变量方便回调函数读取。<br>具体声明了音频流句柄 m_streamIn、当前采样通道数 m_nChannels、采样位宽 m_nSampleSize、采样频率 m_nSampleRate、时间片内帧数 m_nFramesPerBuffer、UDP套接字 m_socket、文件对象 m_file 、计时器对象 m_calcTime。<br>手动添加两个公有函数，showStatus() 函数根据实时采样得到的帧数和字节数，显示到窗口底部状态标签；<br>getSampleFormat() 函数根据采样位宽数值，获取 PA 库对应的采样点数据类型。<br>
    两个私有槽函数是之前通过按钮右键菜单添加的。<br>最后手动添加了界面初始化函数 initUI()，以及在采集时固定采样参数控件的 holdParas() 函数。<br>
          <br>下面分段编辑源文件 widgetpainsimple.cpp，首先是头文件包含、构造函数和析构函数代码：<br>
<div class="code">
<style type="text/css">
p, li { white-space: pre-wrap; }
</style>

<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">"widgetpainsimple.h"</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">"ui_widgetpainsimple.h"</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;QDebug&gt;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;QMessageBox&gt;</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#800080;">WidgetPAInSimple</span><span style=" color:#000000;">::</span><span
style=" color:#000000;">WidgetPAInSimple</span><span style=" color:#000000;">(</span><span
style=" color:#800080;">QWidget</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">*</span><span style=" color:#000000;">parent</span><span
style=" color:#000000;">)</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QWidget</span><span
style=" color:#000000;">(</span><span style=" color:#000000;">parent</span><span
style=" color:#000000;">),</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">new</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">Ui</span><span style=" color:#000000;">::</span><span style=" color:#800080;">WidgetPAInSimple</span><span
style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setupUi</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">this</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//指针初始化为空</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_streamIn</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">NULL</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//先初始化PA库</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">Pa_Initialize</span><span
style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//调用初始化界面函数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">initUI</span><span
style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#800080;">WidgetPAInSimple</span><span style=" color:#000000;">::~</span><span
style=" font-style:italic; color:#000000;">WidgetPAInSimple</span><span style=" color:#000000;">()</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//关闭文件和套接字</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_file</span><span
style=" color:#000000;">.</span><span style=" font-style:italic; color:#000000;">close</span><span
style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_socket</span><span
style=" color:#000000;">.</span><span style=" font-style:italic; color:#000000;">close</span><span
style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//指针置空</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_streamIn</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">NULL</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//终止</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">PA</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">库引用</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">Pa_Terminate</span><span
style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//销毁窗口</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">delete</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre></div>
          
          
          添加了打印调试信息和消息框类的头文件包含。<br>构造函数将指针 m_streamIn 初始化为 NULL；然后调用 Pa_Initialize() 初始化 PA 库；调用 initUI() 初始化界面控件。<br>析构函数将文件对象、套接字对象关闭，将指针 m_streamIn 置空，然后终止 PA 库引用，销毁窗口。<br>
          <br>初始化界面的函数内容如下：<br>
    <div class="code">
<style type="text/css">
p, li { white-space: pre-wrap; }
</style>

<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#008000;">//初始化界面</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">void</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">WidgetPAInSimple</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">initUI</span><span
style=" color:#000000;">()</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//声道数量</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QStringList</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">listChannels</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">listChannels</span><span
style=" color:#000000;">&lt;&lt;</span><span style=" color:#008000;">"1"</span><span
style=" color:#000000;">&lt;&lt;</span><span style=" color:#008000;">"2"</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxChannels</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">addItems</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">listChannels</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//采样位宽，这个示例约定8位无符号整数，16位有符号整数和32位浮点数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QStringList</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">listSampleSizes</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">listSampleSizes</span><span
style=" color:#000000;">&lt;&lt;</span><span style=" color:#008000;">"8"</span><span
style=" color:#000000;">&lt;&lt;</span><span style=" color:#008000;">"16"</span><span
style=" color:#000000;">&lt;&lt;</span><span style=" color:#008000;">"32"</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxSampleSize</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">addItems</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">listSampleSizes</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//设置默认位宽为</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">16，PA库的8位采样有bug，建议16位或以上位宽采样</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxSampleSize</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setCurrentText</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">"16"</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//采样频率，示例枚举比较通用的三个</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QStringList</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">listSampleRates</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">listSampleRates</span><span
style=" color:#000000;">&lt;&lt;</span><span style=" color:#008000;">"8000"</span><span
style=" color:#000000;">&lt;&lt;</span><span style=" color:#008000;">"44100"</span><span
style=" color:#000000;">&lt;&lt;</span><span style=" color:#008000;">"48000"</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxSampleRate</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">addItems</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">listSampleRates</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//时间片帧数范围，8k采样一毫秒8帧，48k采样，一秒钟48000帧</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">spinBoxFramesPerBuffer</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setRange</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000080;">8</span><span
style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000080;">48000</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//默认时间片</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">20</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">毫秒，8k采样就是</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">160</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">帧</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">spinBoxFramesPerBuffer</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setValue</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000080;">160</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//默认IP地址</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">lineEditIP</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setText</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">"127.0.0.1"</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//端口号范围</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">spinBoxPort</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setRange</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000080;">1</span><span
style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000080;">65535</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">spinBoxPort</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setValue</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000080;">12345</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span><span style=" color:#008000;">//默认端口</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//默认文件名</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">lineEditFile</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setText</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">"E:/pasimple_8k1c16bit.pcm"</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//界面设置完毕</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">return</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre></div> 
          
          该函数设置声道数量的字符串列表，添加为声道数量组合框 comboBoxChannels 的条目；<br>设置采样位宽的字符串列表，添加为采样位宽组合框 comboBoxSampleSize 的条目，设置默认位宽为 16；<br>设置采样频率的字符串列表，添加为采样频率组合框 comboBoxSampleRate 的条目；<br>设置旋钮编辑框 spinBoxFramesPerBuffer 数值范围 8 ~ 48000，即 8k 采样 1ms 帧数到 48k 采样 1s 帧数；<br>默认的缓冲区帧数为 160 帧，即时间片内的帧数，在 8k 采样频率情况下，就是 20 ms 的时间片。<br>设置默认目标地址 "127.0.0.1"；<br>设置端口号旋钮编辑框范围 1 到 65535；<br>设置默认端口号为 12345；<br>设置默认的文件名为 "E:/pasimple_8k1c16bit.pcm" ，设置完成后返回。<br><br>该函数之所以设置默认 16 bit 采样位宽，是因为实际测试时发现 PA 库 8bit 采样有 bug，总是采集全 0 数值的样本点。使用 PA 库进行音频输入时，建议用 16bit 和以上的采样位宽。<br>
          <br>接下来我们编辑非常重要的回调函数，将实时的采样数据写入文件和套接字：<br>
<div class="code">
<style type="text/css">
p, li { white-space: pre-wrap; }
</style>

<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#008000;">//先编写回调函数，用户数据保存窗口类对象的this指针</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">static</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">audioInCallback</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">const</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">void</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">*</span><span style=" color:#000000;">inputBuffer</span><span
style=" color:#000000;">,</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                     </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span><span style=" color:#000000;">outputBuffer</span><span
style=" color:#000000;">,</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                     </span><span style=" color:#808000;">unsigned</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">long</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">frameCount</span><span style=" color:#000000;">,</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                     </span><span style=" color:#808000;">const</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">PaStreamCallbackTimeInfo</span><span
style=" color:#000000;">*</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">timeInfo</span><span
style=" color:#000000;">,</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                     </span><span style=" color:#800080;">PaStreamCallbackFlags</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">statusFlags</span><span
style=" color:#000000;">,</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                     </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span><span style=" color:#000000;">userData</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//采集的数据，文件和网络对采样点类型不关心，只需要知道数据的总字节数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">const</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">char</span><span style=" color:#000000;">*</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">dataIn</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">(</span><span style=" color:#808000;">const</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">char</span><span style=" color:#000000;">*)</span><span
style=" color:#000000;">inputBuffer</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//窗口指针</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">WidgetPAInSimple</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span><span style=" color:#000000;">pWnd</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">(</span><span style=" color:#800080;">WidgetPAInSimple</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*)</span><span style=" color:#000000;">userData</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//qint64</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">nsBegin</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">pWnd-&gt;m_calcTime.nsecsElapsed();</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">//本次回调函数开始执行时间</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//计算数据字节数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nChannels</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">pWnd</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#800000;">m_nChannels</span><span style=" color:#000000;">;</span><span
style=" color:#008000;">//通道数量</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nBytesPerSample</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">(</span><span style=" color:#000000;">pWnd</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#800000;">m_nSampleSize</span><span style=" color:#000000;">)</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">/</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">8</span><span style=" color:#000000;">;</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">//样本字节数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nAllBytes</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">frameCount</span><span style=" color:#000000;">*</span><span
style=" color:#000000;">nChannels</span><span style=" color:#000000;">*</span><span
style=" color:#000000;">nBytesPerSample</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//写入文件</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">(</span><span style=" color:#000000;">pWnd</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">m_file</span><span
style=" color:#000000;">).</span><span style=" color:#000000;">write</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">dataIn</span><span
style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nAllBytes</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//写入套接字</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">(</span><span style=" color:#000000;">pWnd</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">m_socket</span><span
style=" color:#000000;">).</span><span style=" color:#000000;">write</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">dataIn</span><span
style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nAllBytes</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//调用状态显示函数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">pWnd</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">showStatus</span><span
style=" color:#000000;">(</span><span style=" color:#000000;">frameCount</span><span
style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nAllBytes</span><span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//qint64</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">nsEnd</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">pWnd-&gt;m_calcTime.nsecsElapsed();</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">//本次回调函数结束时间</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//qDebug()&lt;&lt;"one</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">call</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">ns:</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">"&lt;&lt;nsEnd-nsBegin;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//回调函数一定要有返回值</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">return</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">paContinue</span><span
style=" color:#000000;">;</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//继续采集</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre></div>
          
          
          
          回调函数是全局函数，它的 6 个参数和之前介绍的一模一样，这里的用户数据保存窗口对象的 this 指针。<br>回调函数首先将输入缓冲区转为 const char* 类型，存到 dataIn ；<br>将用户数据指针转为 WidgetPAInSimple * 类型，存到 pWnd 。<br>接下来从窗口对象获取采样通道数 nChannels ，计算一个声道内一个样本点的字节数 nBytesPerSample ；<br>计算缓冲区内所有声道所有样本的总字节数 nAllBytes ；<br>因为写文件和套接字只关心数据字节数，而不用管什么类型，所以只需要知道数据指针和数据总字节数。<br>我们将数据写入到文件对象 pWnd-&gt;m_file 和套接字对象 pWnd-&gt;m_socket；<br>然后调用 pWnd-&gt;showStatus(frameCount, nAllBytes) 显示实时采集的帧数和数据字节数；<br>最后返回 paContinue，表示继续采集，如果返回其他数值或不返回数值，那么采集过程自动停止。<br>正常情况下，回调函数一定要返回 paContinue，表示一直重复采集声卡数据。<br><br>回调函数有三行注释掉的代码，可以解除注释，用于测试回调函数内代码的执行时间，单位纳秒。<br>作者实测一次回调函数调用耗费 121524 纳秒，约等于 0.1 毫秒，远远小于正常采样的时间片，所以不会干扰采样的流畅性。<br>
          <br>接下来编辑实时显示状态字符串的函数：<br>
   <div class="code">
<style type="text/css">
p, li { white-space: pre-wrap; }
</style>

<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#008000;">//设置状态字符串</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">void</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">WidgetPAInSimple</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">showStatus</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">nFrames</span><span style=" color:#000000;">,</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">nBytes</span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QString</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strStatus</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">qint64</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">msCount</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800000;">m_calcTime</span><span style=" color:#000000;">.</span><span
style=" color:#000000;">elapsed</span><span style=" color:#000000;">();</span><span
style=" color:#008000;">//毫秒数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//构造状态字符串</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">strStatus</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span style=" color:#008000;">"%1.%2</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">s,</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">%3</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">frames,</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">%4</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">bytes"</span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">            </span><span style=" color:#000000;">.</span><span
style=" color:#000000;">arg</span><span style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">msCount</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">/</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000080;">1000</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">            </span><span style=" color:#000000;">.</span><span
style=" color:#000000;">arg</span><span style=" color:#000000;">(</span><span style=" color:#000000;">msCount</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">%</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">1000</span><span style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">3</span><span style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">10</span><span style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">QChar</span><span style=" color:#000000;">(</span><span
style=" color:#008000;">'0'</span><span style=" color:#000000;">))</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">            </span><span style=" color:#000000;">.</span><span
style=" color:#000000;">arg</span><span style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">nFrames</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">            </span><span style=" color:#000000;">.</span><span
style=" color:#000000;">arg</span><span style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">nBytes</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">labelStatus</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setText</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strStatus</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span><span style=" color:#008000;">//显示到状态条</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">return</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre></div>
          
          
          定时器 m_calcTime.elapsed() 是获取自定时器开始之后的毫秒时间，m_calcTime.nsecsElapsed() 是获取纳秒时间，一般获取到毫秒时间就足够了。<br>我们从毫秒时间提取出秒数和毫秒余数，构造字符串，显示计时器时间和采样帧数、数据字节数等信息到窗口的状态标签 labelStatus 。<br>
          <br>接下来编辑一个简单的功能函数，根据采样位宽获取对应的 PA 库采样点数据类型：<br>
<div class="code">
<style type="text/css">
p, li { white-space: pre-wrap; }
</style>

<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#008000;">//根据采样位宽获取采样点数据格式</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#800080;">PaSampleFormat</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">WidgetPAInSimple</span><span style=" color:#000000;">::</span><span
style=" color:#000000;">getSampleFormat</span><span style=" color:#000000;">(</span><span
style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">sampleSize</span><span
style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">switch</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">(</span><span style=" color:#000000;">sampleSize</span><span
style=" color:#000000;">)</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">case</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">8</span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">return</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">paUInt8</span><span
style=" color:#000000;">;</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//8位无符号整数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">break</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">case</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">16</span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">return</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">paInt16</span><span
style=" color:#000000;">;</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//16位有符号整数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">break</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">case</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">32</span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">return</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">paFloat32</span><span
style=" color:#000000;">;</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//32位浮点数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">break</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">default</span><span
style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">return</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">paInt16</span><span
style=" color:#000000;">;</span><span style=" color:#008000;">//16位有符号整数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">break</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre></div>
          
          
          当采样位宽是 8 时，返回类型 paUInt8；采样位宽为 16 时，返回类型 paInt16；采样位宽为 32 时，返回类型 paFloat32；其他情况都返回 paInt16 。我们这里挑选了三种常用的数据类型，PA 库也支持其他类型，这个示例做了一下简化，只用了三种采样点数据类型。这个功能函数会在打开流时使用。 <br>
          <br>下面编辑“开始”按钮的槽函数：<br>
 <div class="code">
<style type="text/css">
p, li { white-space: pre-wrap; }
</style>

<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">void</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">WidgetPAInSimple</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">on_pushButtonStart_clicked</span><span
style=" color:#000000;">()</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//尝试打开文件</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_file</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">setFileName</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">lineEditFile</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">text</span><span
style=" color:#000000;">()</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">if</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">!</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_file</span><span
style=" color:#000000;">.</span><span style=" font-style:italic; color:#000000;">open</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QIODevice</span><span
style=" color:#000000;">::</span><span style=" color:#800080;">WriteOnly</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">)</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800080;">QMessageBox</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">warning</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">this</span><span style=" color:#000000;">,</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span
style=" color:#008000;">"打开文件"</span><span style=" color:#000000;">),</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span
style=" color:#008000;">"打开文件失败，请检查文件名和权限。"</span><span style=" color:#000000;">));</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">return</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//尝试转换字符串为IP地址对象</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QHostAddress</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">ipAddr</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">if</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">!</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">ipAddr</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">setAddress</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">lineEditIP</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">text</span><span
style=" color:#000000;">()</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">)</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800080;">QMessageBox</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">warning</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">this</span><span style=" color:#000000;">,</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span
style=" color:#008000;">"IP地址"</span><span style=" color:#000000;">),</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span
style=" color:#008000;">"IP地址不合法。"</span><span style=" color:#000000;">));</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">m_file</span><span
style=" color:#000000;">.</span><span style=" font-style:italic; color:#000000;">close</span><span
style=" color:#000000;">();</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//文件释放</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">return</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">quint16</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nPort</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800000;">ui</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#800000;">spinBoxPort</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#000000;">value</span><span style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//设置UDP套接字的目标地址和端口</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_socket</span><span
style=" color:#000000;">.</span><span style=" font-style:italic; color:#000000;">connectToHost</span><span
style=" color:#000000;">(</span><span style=" color:#000000;">ipAddr</span><span
style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nPort</span><span
style=" color:#000000;">);</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//获取录音参数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_nChannels</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800000;">ui</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#800000;">comboBoxChannels</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#000000;">currentText</span><span style=" color:#000000;">().</span><span
style=" color:#000000;">toInt</span><span style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_nSampleSize</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800000;">ui</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#800000;">comboBoxSampleSize</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#000000;">currentText</span><span style=" color:#000000;">().</span><span
style=" color:#000000;">toInt</span><span style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_nSampleRate</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800000;">ui</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#800000;">comboBoxSampleRate</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#000000;">currentText</span><span style=" color:#000000;">().</span><span
style=" color:#000000;">toInt</span><span style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_nFramesPerBuffer</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800000;">ui</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#800000;">spinBoxFramesPerBuffer</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#000000;">value</span><span style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//打开流</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">PaError</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">err</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">Pa_OpenDefaultStream</span><span
style=" color:#000000;">(</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                </span><span style=" color:#000000;">&amp;</span><span
style=" color:#800000;">m_streamIn</span><span style=" color:#000000;">,</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                </span><span style=" color:#800000;">m_nChannels</span><span
style=" color:#000000;">,</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                </span><span style=" color:#000080;">0</span><span
style=" color:#000000;">,</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                </span><span style=" color:#000000;">getSampleFormat</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_nSampleSize</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">),</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                </span><span style=" color:#800000;">m_nSampleRate</span><span
style=" color:#000000;">,</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                </span><span style=" color:#800000;">m_nFramesPerBuffer</span><span
style=" color:#000000;">,</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                </span>audioInCallback<span style=" color:#000000;">,</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//回调函数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                </span><span style=" color:#000000;">(</span><span
style=" color:#808000;">void</span><span style=" color:#000000;">*)</span><span
style=" color:#808000;">this</span><span style=" color:#c0c0c0;">      </span><span
style=" color:#008000;">//窗口对象指针</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QString</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strErr</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//判断是否有错</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">if</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">paNoError</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">!=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">err</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#008000;">//显示错误消息</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#000000;">strErr</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span style=" color:#008000;">"PortAudio</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">error:</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">%1"</span><span style=" color:#000000;">).</span><span
style=" color:#000000;">arg</span><span style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">Pa_GetErrorText</span><span style=" color:#000000;">(</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">err</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">)</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800080;">QMessageBox</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">warning</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">this</span><span style=" color:#000000;">,</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span
style=" color:#008000;">"Pa_OpenDefaultStream"</span><span style=" color:#000000;">),</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strErr</span><span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">m_file</span><span
style=" color:#000000;">.</span><span style=" font-style:italic; color:#000000;">close</span><span
style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">return</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//开始流</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">err</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">Pa_StartStream</span><span style=" color:#000000;">(</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_streamIn</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">if</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">paNoError</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">!=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">err</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#008000;">//显示错误消息</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#000000;">strErr</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span style=" color:#008000;">"PortAudio</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">error:</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">%1"</span><span style=" color:#000000;">).</span><span
style=" color:#000000;">arg</span><span style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">Pa_GetErrorText</span><span style=" color:#000000;">(</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">err</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">)</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800080;">QMessageBox</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">warning</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">this</span><span style=" color:#000000;">,</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span
style=" color:#008000;">"Pa_StartStream"</span><span style=" color:#000000;">),</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strErr</span><span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">m_file</span><span
style=" color:#000000;">.</span><span style=" font-style:italic; color:#000000;">close</span><span
style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">return</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_calcTime</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">start</span><span
style=" color:#000000;">();</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//计时开始</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//禁用输入控件，固定参数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">holdParas</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">true</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre></div>
          
          该槽函数先设置文件名，尝试打开文件，如果打开文件失败，弹出消息框提示打开失败，直接返回；如果打开成功继续后面代码。<br>定义地址对象，尝试将 IP 字符串设置给地址对象，如果设置失败，弹窗显示 IP 地址格式不合法，关闭文件后返回；如果 IP 合法，继续后面代码。<br>获取端口号，因为之前设置过端口号范围，所以不需要判断端口号数值；<br>调用套接字的连接主机函数，设置套接字对象的目标主机 IP 和端口；<br>接着获取采样参数：通道数 m_nChannels、采样位宽 m_nSampleSize、采样频率 m_nSampleRate 和缓冲区帧数 m_nFramesPerBuffer，缓冲区帧数就对应时间片内的帧数，缓冲区帧数 / 采样频率 就是采样的时间片。<br><br>然后我们调用 Pa_OpenDefaultStream() 打开默认音频流，8 个参数分别为指向流句柄的指针 &amp;m_streamIn、输入通道数 m_nChannels 、输出声道数 0、采样点数据格式 getSampleFormat( m_nSampleSize )、采样频率 m_nSampleRate、缓冲区内帧数 m_nFramesPerBuffer、回调函数指针 audioInCallback 和窗口对象指针。<br>调用后检查返回值，如果不等于 paNoError，说明打开流失败，显示错误消息框，关闭文件，返回。<br>如果打开流成功，就调用 Pa_StartStream( m_streamIn )，开始音频流；<br>一样要检查返回值，如果调用出错就显示错误消息框，关闭文件并返回。<br>如果开始流成功，那么开始计时器 m_calcTime.start()；<br>禁用窗口的输入控件和“开始”按钮。<br><br> 简单接口 Pa_OpenDefaultStream() 没有设置底层音频框架和设备的参数，都是用默认的音频框架和设备。后面介绍的复杂接口 Pa_OpenStream() 可以自己设置音频框架和设备。<br>
          <br>接下来编辑采集时固定界面参数的函数：<br>
  <div class="code">
<style type="text/css">
p, li { white-space: pre-wrap; }
</style>

<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#008000;">//采集时固定参数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">void</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">WidgetPAInSimple</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">holdParas</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">bool</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">bHold</span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxChannels</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setDisabled</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">bHold</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxSampleSize</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setDisabled</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">bHold</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxSampleRate</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setDisabled</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">bHold</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">lineEditIP</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setDisabled</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">bHold</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">lineEditFile</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setDisabled</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">bHold</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">spinBoxFramesPerBuffer</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setDisabled</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">bHold</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">spinBoxPort</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setDisabled</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">bHold</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">pushButtonStart</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setDisabled</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">bHold</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre></div>
          
          
          该函数在参数为 true 时，设置各个输入控件和“开始”按钮禁用；<br>在参数为 false 时，设置各个输入控件和“开始”按钮重新启用。<br>
          <br>最后是“停止”按钮的槽函数：<br>
<div class="code">
<style type="text/css">
p, li { white-space: pre-wrap; }
</style>

<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">void</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">WidgetPAInSimple</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">on_pushButtonStop_clicked</span><span
style=" color:#000000;">()</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//判断流是否在工作</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">if</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">Pa_IsStreamActive</span><span
style=" color:#000000;">(</span><span style=" color:#800000;">m_streamIn</span><span
style=" color:#000000;">)</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">&lt;=</span><span
style=" color:#000080;">0</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#008000;">//流没有开始或者处于错误状态，不需要停止</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">return</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">}</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">PaError</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">err</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">qint64</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">msCount</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800000;">m_calcTime</span><span style=" color:#000000;">.</span><span
style=" color:#000000;">elapsed</span><span style=" color:#000000;">();</span><span
style=" color:#008000;">//结束时间毫秒数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//流正在工作，停止流</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">err</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">Pa_StopStream</span><span style=" color:#000000;">(</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_streamIn</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">err</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">Pa_CloseStream</span><span style=" color:#000000;">(</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_streamIn</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">if</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">paNoError</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">!=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">err</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#008000;">//显示错误消息</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800080;">QString</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strErr</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span style=" color:#008000;">"PortAudio</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">error:</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">%1"</span><span style=" color:#000000;">).</span><span
style=" color:#000000;">arg</span><span style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">Pa_GetErrorText</span><span style=" color:#000000;">(</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">err</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">)</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800080;">QMessageBox</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">warning</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">this</span><span style=" color:#000000;">,</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span
style=" color:#008000;">"Pa_CloseStream"</span><span style=" color:#000000;">),</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strErr</span><span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//关闭文件</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_file</span><span
style=" color:#000000;">.</span><span style=" font-style:italic; color:#000000;">close</span><span
style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_socket</span><span
style=" color:#000000;">.</span><span style=" font-style:italic; color:#000000;">disconnectFromHost</span><span
style=" color:#000000;">();</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//断开</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_streamIn</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">NULL</span><span style=" color:#000000;">;</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">//指针置空</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//恢复控件</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">holdParas</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">false</span><span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QString</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strStatus</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span style=" color:#008000;">"采集结束，耗时：%1.%2</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">s"</span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">            </span><span style=" color:#000000;">.</span><span
style=" color:#000000;">arg</span><span style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">msCount</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">/</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000080;">1000</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">            </span><span style=" color:#000000;">.</span><span
style=" color:#000000;">arg</span><span style=" color:#000000;">(</span><span style=" color:#000000;">msCount</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">%</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">1000</span><span style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">3</span><span style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">10</span><span style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">QChar</span><span style=" color:#000000;">(</span><span
style=" color:#008000;">'0'</span><span style=" color:#000000;">));</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//显示状态</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">labelStatus</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setText</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strStatus</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre></div>
          
          
          该函数先对音频的活跃状态进行判断，如果不是活跃状态，那么说明流处于停止、没开始或出错状态，不需要停止操作，直接返回。<br>如果流正处于采集状态，那么先获取采集过程花费的时间 msCount；<br>调用 Pa_StopStream( m_streamIn ) 停止流；<br>调用 Pa_CloseStream( m_streamIn ) 关闭流，并对返回值做判断，如果出错就显示错误消息框。<br>然后关闭文件，断开套接字连接；<br>将流句柄置空；<br>恢复界面的控件为可用状态；<br>构造状态字符串，显示采集结束和采集耗时的信息。<br>一般每个 PA 库函数都带有返回值，如果出错就可以判断错误代码，获取出错信息字符串，示例对返回值判断做了省略，只判断了打开流、开始流和关闭流函数的返回值。<br>
          <br>本示例代码介绍到这，我们将麦克风、耳机或音箱连接到电脑，构建运行示例，点击“开始”按钮：<br>
           <center> <img src="images/ch03/ch03-04-02.png" alt="run">
          </center>
          
          可以看到示例正常运行，并且不断写入数据到指定文件 pasimple_8k1c16bit.pcm，停止采样后，我们可以用 3.2.2 节 playfile 播放该文件。或者在本示例采样的同时用 3.2.3 节 playudp 做网络接收和播放。<br>要注意修改 playfile 和 playudp 播放参数，采样位宽为 16，数据类型为有符号整数。<br><b>如果播放时的采样位宽和数据类型设置出错，那么会听到噪音。</b><br>
    我们下面小节介绍基于 Pa_OpenStream() 的复杂接口。<br><br>
    <div class="os2">3.4.3 PortAudio 复杂接口及采集示例 </div>
    <br>
    <b>PA 库复杂接口的工作流程与简单接口的工作流程几乎一模一样，区别仅仅是将上面小节的 Pa_OpenDefaultStream() 换成 Pa_OpenStream() 函数。所谓的复杂，就是 Pa_OpenStream() 函数的参数要复杂一点，其实二者用起来都很简单。</b><br><br> Pa_OpenStream() 函数可以自己挑选底层音频框架和设备，在介绍该函数之前，我们先来了解一下查询底层音频框架和设备的函数。
          <br>底层音频框架和设备的可以借助如下示意图来理解：<br>
            <center> <img src="images/ch03/portaudiomap.png">
          </center>
          
          上图显示有两个底层音频框架（HostAPI）：WMME 框架和 DirectSound 框架，每个音频框架管理四个设备，设备可以是系统模拟的虚拟设备，也可以是真实的物理声卡。<br>音频框架管理设备时的序号为设备相对序号，无论是哪个音频框架的设备，将所有设备全部列举在一起的时候，每个设备都有其绝对序号。根据音频框架序号和设备相对序号可以查询到设备的绝对序号。<br><br>下面我们先介绍获取音频框架和设备的函数，然后介绍基于 Pa_OpenStream() 函数的复杂接口。<br>（1）获取音频框架的函数<br>获取支持的音频框架数量，使用下面函数：<br>
          <div class="code">PaHostApiIndex Pa_GetHostApiCount( void );</div>
          
          如果存在支持的音频框架，返回值大于等于 0，是正常的音频框架计数；
          如果 PA 库初始化失败，会导致音频框架的计数是负数，即错误代号。
          正常情况下，音频框架的序号是 0 到 Pa_GetHostApiCount()-1。 <br>
            获取默认的音频框架序号，使用下面函数：<br>
          <div class="code">PaHostApiIndex Pa_GetDefaultHostApi( void );</div>
          
          
          根据音频框架序号，获取框架详细信息的函数为：<br>
           <div class="code">const PaHostApiInfo * Pa_GetHostApiInfo( PaHostApiIndex hostApi );</div>
          
          参数序号如果不合法，返回指针为 NULL；参数如果合法，即 0 到 Pa_GetHostApiCount()-1 的序号，返回值是结构体对象的指针，包含音频框架的信息。<br>
          PaHostApiInfo 结构体声明如下：<br>
 <div class="code">typedef struct PaHostApiInfo<br>{<br>&nbsp;&nbsp;&nbsp; int structVersion;<br>&nbsp;&nbsp;&nbsp; PaHostApiTypeId type;<br>&nbsp;&nbsp;&nbsp; <b>const char *name;</b>//框架名称字符串<br><br>&nbsp;&nbsp;&nbsp; <b>int deviceCount; </b>//框架管理的设备数量<br><br>&nbsp;&nbsp;&nbsp; <b>PaDeviceIndex defaultInputDevice;</b>//默认输入设备绝对序号<br><br>&nbsp;&nbsp;&nbsp;<b> PaDeviceIndex defaultOutputDevice;</b>//默认输出设备绝对序号<br>&nbsp;&nbsp; &nbsp;<br>} PaHostApiInfo;</div>
          
          
          
          PaHostApiInfo 结构体内有六个成员变量：<br>① structVersion 是结构体声明的版本，这个变量可以忽略，没什么用；<br>② type 是指 PA 库对所支持音频框架的统一编号，目前 PA 库支持的底层音频框架如下表所示：<br>
  <br>
          <table class="tabel">
            <tbody>
              <tr class="d1">
                <td style="width: 240px;" align="center"><b>PaHostApiTypeId&nbsp;
                    枚举常量</b></td>
                <td style="width: 100px;" align="center"><b>数值</b></td>
                <td align="center"><b> 描述</b></td>
              </tr>
              <tr>
                <td>paInDevelopment</td>
                <td> 0</td>
                <td> 用于正在开发中的新支持的音频框架。 </td>
              </tr>
              <tr class="d1">
                <td><b>paDirectSound</b></td>
                <td> 1</td>
                <td> Windows系统 DirectSound 音频框架。 </td>
              </tr>
              <tr>
                <td><b>paMME</b> </td>
                <td> 2</td>
                <td> Windows系统 MME 音频框架（windows multimedia extensions，即 Windows Multimedia API）。 </td>
              </tr>
              <tr class="d1">
                <td><b>paASIO</b></td>
                <td> 3</td>
                <td> Windows系统专业声卡驱动模式，ASIO 全称 Audio Stream Input Output，由 Steinberg 公司开发，采用 ASIO 技术可以减少系统对音频流信号的延迟，增强声卡硬件的处理能力。 </td>
              </tr>
              <tr>
                <td>paSoundManager</td>
                <td> 4</td>
                <td> MacOS Classic SoundManager 音频框架，已废弃。 </td>
              </tr>
                <tr class="d1">
                <td><b>paCoreAudio</b></td>
                <td> 5</td>
                <td> Mac OS X 系统 Core Audio 音频框架。 </td>
              </tr>
              <tr>
                <td>--</td>
                <td> 6</td>
                <td style="height: 15px;"> 没有该枚举值。 </td>
              </tr>
                <tr class="d1">
                <td><b>paOSS</b></td>
                <td> 7</td>
                <td> Unix/Linux 系统 OSS (Open Sound System) 音频框架。 </td>
              </tr>
              <tr>
                <td><b>paALSA</b></td>
                <td> 8</td>
                <td> Unix/Linux 系统 ALSA (Advanced Linux Sound Architechture) 音频框架。 </td>
              </tr>
                <tr class="d1">
                <td>paAL</td>
                <td> 9</td>
                <td> 已废弃，硅谷图形公司（Silicon Graphics Inc，SGI）Irix 操作系统的 AL 音频框架。 </td>
              </tr>
              <tr>
                <td>paBeOS</td>
                <td> 10</td>
                <td> 已废弃，BeOS是由 Be 公司开发的一种多媒体操作系统，由于 Be 公司被收购，该系统已经被废止。 </td>
              </tr>
                <tr class="d1">
                <td><b>paWDMKS</b></td>
                <td> 11</td>
                <td style="height: 15px;"> Windows系统 WDM-KS（Windows Driver Model-Kernel Streaming）内核流式处理框架，直接从内核层提供低延迟的音频采集或播放。 </td>
              </tr>
              <tr>
                <td><b>paJACK</b></td>
                <td> 12</td>
                <td> Unix/Linux 系统 Jack（JACK Audio Connection Kit 递归命名）音频框架，它为声音和MIDI数据提供实时的、低延时的连接。 </td>
              </tr>
                <tr class="d1">
                <td><b>paWASAPI</b></td>
                <td> 13</td>
                <td> Windows系统 WASAPI 音频框架，全称是Windows Audio Session API(Windows音频会话API)，从 Windows&nbsp; Vista 系统开始支持。</td>
              </tr>
              <tr>
                <td><b>paAudioScienceHPI</b></td>
                <td> 14</td>
                <td> ASIHPI 音频框架，通过 Linux HPI 接口支持 AudioScience 声卡的音频框架。 </td>
              </tr>
            </tbody>
          </table>
          <br>
          
          上表中粗体的10种音频框架（DirectSound、WMME、ASIO、CoreAudio、OSS、ALSA、WDMKS、JACK、WASAPI、ASIHPI）是目前实际支持的，其他是占空位的。<br>
    ③ name，这是音频框架的名称字符串，是上面 PaHostApiTypeId 对应的可读字符串，一般界面都是显示字符串，而不会直接显示类型数值。<br>④ deviceCount 是音频框架管理的设备数量，有可能包含虚拟设备和真实设备，也可能没有任何设备。音频框架管理的设备的相对序号是从 0 到 deviceCount-1 。<br>⑤ defaultInputDevice 是音频框架默认使用的输入设备绝对序号，正常范围是 0 到 Pa_GetDeviceCount()-1 ，如果没有输入设备，那么数值就是 paNoDevice 。<br>⑥ defaultOutputDevice 是音频框架默认使用的输出设备绝对序号，正常范围是  0 到 Pa_GetDeviceCount()-1 ，如果没有输出设备，那么数值就是 paNoDevice 。<br>paNoDevice 本身的数值就是 -1，代表没有设备可用。<br>
          <br>
    （2）获取所有设备的函数<br>
          不区分所属音频框架的情况下，获取 PA 库所有可用的音频设备数量函数如下：<br>
  <div class="code">PaDeviceIndex Pa_GetDeviceCount( void );</div>
   正常情况下，所有设备的绝对序号范围是 0 到 Pa_GetDeviceCount()-1 。<br>音频设备数量有可能是 0，说明没有可用的设备。<br>如果返回的计数是负数，说明 PA 库发生错误，返回值是错误代码。<br><br>获取 PA 库默认输入设备、默认输出设备的绝对序号，使用下面两个函数：<br>       
  <div class="code">PaDeviceIndex Pa_GetDefaultInputDevice( void ); //默认输入设备绝对序号<br>PaDeviceIndex Pa_GetDefaultOutputDevice( void );//默认输出设备绝对序号</div>
   正常情况下，返回的绝对序号范围是从 0 到 Pa_GetDeviceCount()-1 ，如果发生没有设备或发生错误，返回的序号是 paNoDevice 。<br>根据设备的绝对序号，获取设备详细信息的函数如下：<br>       
   <div class="code">const PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceIndex device );</div>
   参数必须使用合法的序号，如果序号不合法，返回指针是 NULL；<br>序号合法的情况下，返回值是设备信息结构体对象的指针，PaDeviceInfo 结构体声明如下：<br>       
    <div class="code">typedef struct PaDeviceInfo<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp; int structVersion;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp; <b>const char *name;</b><br>&nbsp;&nbsp;&nbsp;&nbsp; <b>PaHostApiIndex hostApi;</b> <br>&nbsp;&nbsp;&nbsp;&nbsp; <b>int maxInputChannels;</b><br>&nbsp;&nbsp;&nbsp;&nbsp; <b>int maxOutputChannels;</b><br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp; PaTime defaultLowInputLatency;//时间单位是秒，下面三个时间单位一样<br>&nbsp;&nbsp;&nbsp;&nbsp; PaTime defaultLowOutputLatency;<br>&nbsp;&nbsp;&nbsp;&nbsp; PaTime defaultHighInputLatency;<br>&nbsp;&nbsp;&nbsp;&nbsp; PaTime defaultHighOutputLatency;<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp; double defaultSampleRate;<br>} PaDeviceInfo;</div>
   PaDeviceInfo 结构体包括 10 个成员变量：<br>① structVersion 是结构体声明的版本号，一般用不到。<br>② name 是设备名称字符串，有可能是虚拟设备，也可能是真实设备。<br>③ hostApi 是设备所属的音频框架序号（不是类型值PaHostApiInfo.type），序号范围是 0 到 Pa_GetHostApiCount()-1。 <br>④ maxInputChannels 是设备支持的音频输入通道上限，有可能为 0。<br>⑤ maxOutputChannels 是设备支持的音频输出通道上限，有可能为 0。<br>⑥ defaultLowInputLatency 是默认输入延迟低值，用于鲁棒的非交互式音频程序，一般用不到。<br>⑦ defaultLowOutputLatency 是默认输出延迟低值，用于鲁棒的非交互式音频程序，一般用不到。<br>⑧ defaultHighInputLatency 是默认输入延迟高值，用于鲁棒的非交互式音频程序，一般用不到。<br>⑨ defaultHighOutputLatency 是默认输出延迟高值，用于鲁棒的非交互式音频程序，一般用不到。<br>⑩ defaultSampleRate 是设备建议使用的默认采样频率。<br><br>       
          
          
          
          （3）根据音频框架序号和设备相对序号 查询 设备绝对序号<br>
根据音频框架序号和它管理的设备相对序号，可以查询该设备的绝对序号，使用下面函数：<br>
 
<div class="code">PaDeviceIndex Pa_HostApiDeviceIndexToDeviceIndex( PaHostApiIndex hostApi, int hostApiDeviceIndex );</div>
          
          该函数第一个参数 hostApi 取值范围从 0 到 (Pa_GetHostApiCount()-1)，第二个参数取值范围从 0 到 (Pa_GetHostApiInfo(hostApi)-&gt;deviceCount - 1) 。<br>
正常情况下返回值是从 0 到 Pa_GetDeviceCount()-1 合法范围的设备绝对序号；<br>
如果出现错误，那么返回值是负数，即错误代号。<br>当错误代号为 paInvalidHostApi，说明第一个参数音频框架序号不合法；<br>当错误代号为 paInvalidDevice 时，说明第二个参数设备相对序号不合法。<br>
<br>（4）PaStreamParameters 流参数结构体<br>在介绍复杂接口  Pa_OpenStream() 函数之前，需要介绍该函数使用的重要参数，即流参数结构体 PaStreamParameters，
          这个流参数结构体对输入流和输出流是通用的，其声明如下：<br>
   <div class="code">typedef struct PaStreamParameters<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp; PaDeviceIndex device;<br>&nbsp;&nbsp;&nbsp;&nbsp; int channelCount;<br>&nbsp;&nbsp;&nbsp;&nbsp; PaSampleFormat sampleFormat;<br>&nbsp;&nbsp;&nbsp;&nbsp; PaTime suggestedLatency;<br>&nbsp;&nbsp;&nbsp;&nbsp; void *hostApiSpecificStreamInfo;<br>} PaStreamParameters;</div>
          
          
          
          PaStreamParameters 有 5 个成员变量：<br>① device 是设备的绝对序号，范围从 0 到 (Pa_GetDeviceCount()-1) 。注意音频输入时要设置输入设备绝对序号，音频输出时要设置输出设备绝对序号，否则会导致&nbsp; Pa_OpenStream() 函数执行错误。 <br>② channelCount 是输入或输出时的声道数量，不超过设备支持的上限值即可，通过 PaDeviceInfo 结构体可以查询设备输入、输出声道数量的上限值。<br>③ sampleFormat 是采样点的数据格式，就是之前 PaSampleFormat 枚举常量表格中列举的格式。<br>④ suggestedLatency 是期望的采样延迟，单位是秒，采样延迟通常不小于我们设置的采样时间片。这只是建议值，实际使用的延迟数值在流开始之后，通过 Pa_GetStreamInfo() 获取 PaStreamInfo 结构体 查询输入、输出延迟。<br>⑤ hostApiSpecificStreamInfo 是针对特定音频框架定制的流设置信息，一般都设置为 NULL，不使用该变量。<br>
          <br>在设置 PaStreamParameters 结构体对象之后，可以查询结构体里的设备是否支持各项参数：<br>
<div class="code">PaError Pa_IsFormatSupported( const PaStreamParameters *inputParameters,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const PaStreamParameters *outputParameters,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; double sampleRate );</div>
          
          如果只查询输入参数或只查询输出参数，另一个 PaStreamParameters 指针可以设置为空。<br>该函数根据参数里的结构体对象指针和采样频率，查询设备是否支持这些参数：<br>如果返回值为 paFormatIsSupported（数值为 0 ），说明格式是受支持的；<br>返回值如果是负数，说明是错误代码，存在不支持的参数，Pa_GetErrorText( errorCode ) 可以查询出错的信息字符串。<br><br>（5）复杂接口  Pa_OpenStream() 函数<br>简单接口和复杂接口的工作流程几乎一样，只是   Pa_OpenStream() 函数的参数复杂一点。
          Pa_OpenStream() 函数的声明如下：<br>
<div class="code">PaError Pa_OpenStream( PaStream** pstream,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const PaStreamParameters *inputParameters,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const PaStreamParameters *outputParameters,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; double sampleRate,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned long framesPerBuffer,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PaStreamFlags streamFlags,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PaStreamCallback *streamCallback,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void *userData );</div>
          
          该函数如果工作正常，返回 paNoError，否则返回负数的错误代号。<br>该函数的参数有 8 个，依次介绍如下：<br>① pstream 是指向流句柄的指针，该函数会创建流句柄，分配流所需的资源。 <br>② inputParameters 是输入流参数结构体对象的指针，用于设置输入流的参数，注意结构体里的设备必须是音频输入设备的绝对序号。<br>③ outputParameters 是输出流参数结构体对象的指针，用于设置输出流参数，注意结构体里的设备必须是音频输出设备的绝对序号。<br>④ sampleRate 是采样频率，音频输入、输出使用同一个采样频率。<br>⑤ framesPerBuffer 是缓冲区帧数，即采样时间片里的帧数，framesPerBuffer/sampleRate 就是采样时间片。如果设置该参数为 paFramesPerBufferUnspecified（数值 0 ），PA 库会自动设置缓冲区帧数和采样时间片。<br>⑥ streamFlags 是流标志位，用于控制流的行为特性，
          多个标志位可以用二进制 OR 同时启用，具体的标志位如下表所示：<br>
             <br>
    <table class="tabel">
      <tbody>
        <tr class="d1">
          <td style="width: 280px;" align="center"><b>PaStreamFlags 流标志位<br></b></td>
          <td style="width: 100px;" align="center"><b>数值</b></td>
          <td align="center"><b> 描述</b></td>
        </tr>
        <tr>
          <td>paNoFlag</td>
          <td> 0</td>
          <td> 没有标志位，默认特性。 </td>
        </tr>
        <tr class="d1">
          <td>paClipOff</td>
          <td> 0x00000001</td>
          <td> 禁用 默认情况下自动切除超出范围样本点的特性。 </td>
        </tr>
        <tr>
          <td>paDitherOff </td>
          <td> 0x00000002</td>
          <td> 禁用 默认的音频抖动特性。 </td>
        </tr>
          <tr class="d1">
          <td>paNeverDropInput</td>
          <td> 0x00000004</td>
          <td style="height: 75px;"> 仅对全双工（支持同时输入和输出）回调函数音频流有用，并且打开音频流时要带paFramesPerBufferUnspecified 缓冲区参数。<br>该标志位设置后，PA库不会丢弃音频输入溢出的过量数据，会将数据都提供给回调函数。 </td>
        </tr>
        <tr>
          <td>paPrimeOutputBuffersUsingStreamCallback </td>
          <td> 0x00000008</td>
          <td> 使用回调函数填充最初的音频输出缓冲区，而不使用默认的全0值缓冲区作为最初的输出缓冲区。<br>该标志位对 仅输入流、阻塞式输入输出流无效。<br> </td>
        </tr>
          <tr class="d1">
          <td>paPlatformSpecificFlags</td>
          <td> 0xFFFF0000</td>
          <td> 根据特定平台定制的标志位模板，一般用不到。 </td>
        </tr>
       
      </tbody>
    </table>
    <br>在通常情况下，我们设置标志位为默认值 paNoFlag 即可。<br><br>⑦ streamCallback 是自定义的回调函数名称，比如上一小节示例的 audioInCallback 函数。<br>⑧ userData 是自定义的用户数据指针，该指针会原封不动地传递给回调函数，也就是回调函数最后一个参数值。可以将采样格式信息或者窗口对象 this 指针等传递给回调函数，方便回调函数获取流信息。 <br><br>虽然&nbsp; Pa_OpenStream() 函数接口同时带有音频输入和输出参数，但是底层音频框架和设备不一定同时支持打开音频输入、输出，所以建议一个音频流句柄只管理输入或只管理输出，输入流和输 出流一般分开使用。<br>输入和输出分开后，也使得单个回调函数的代码简化，只需要处理输入数据或只处理输出数据，减少回调函数的执行时间。<br><br><b>PA库的复杂接口只有  Pa_OpenStream() 函数与简单接口 Pa_OpenDefaultStream() 函数不一样，其他如开始流、停止流、中断流、关闭流、回调函数等内容，都与简单接口的使用一模一样。</b><br><br>（7）其他信息查询函数<br>之前介绍过 Pa_IsStreamStopped()、Pa_IsStreamActive()、Pa_GetStreamTime() 等状态查询函数，这里补充介绍几个关于流信息的查询函数。
          <br>在流开始之后，可以查询流信息结构体对象：<br>
          <div class="code">const PaStreamInfo* Pa_GetStreamInfo( PaStream *stream );</div>
          
          PaStreamInfo 结构体内容比较简单：<br>
<div class="code">typedef struct PaStreamInfo<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp; int structVersion;<br>&nbsp; &nbsp;&nbsp; PaTime inputLatency; <br>&nbsp;&nbsp;&nbsp;&nbsp; PaTime outputLatency; <br>&nbsp;&nbsp;&nbsp;&nbsp; double sampleRate;&nbsp;&nbsp;&nbsp;&nbsp; <br>} PaStreamInfo;</div>
          
          
          第一个 structVersion 是结构体声明版本，一般用不到。<br>第二个 inputLatency 是输入音频流实际的输入延迟，单位是秒，有可能与 Pa_OpenStream() 参数里指定的延迟数值差异很大，通常输入延迟不小于采样时间片，可能是采样时间片的一倍或多倍。对于仅输出流，没有采集数据，输入延迟为 0。<br>第三个 outputLatency 是输出音频实际的输出延迟，单位是秒，有可能与 Pa_OpenStream() 参数里指定的延迟数值差异很大，通常输出延迟不小于播放时间片，可能是播放时间片的一倍或多倍。对于仅输入流，不播放数据，输出延迟为 0。<br>第四个 sampleRate 是采样频率，这个变量是防止硬件声卡实际工作的采样频率与之前设置的不一样，专门保存声卡硬件实际工作的采样频率。通常情况下，只要采样频率是声卡设备支持的，这个数值都与 Pa_OpenStream() 参数设置的数值一样。<br><br>因为 PA 库多数情况下都是用回调函数机制实现音频采集和播放，回调函数有可能耗费较多的 CPU 资源，
          所以 PA 库专门提供了一个函数查询音频流占用的 CPU 负载：<br>
          <div class="code">double Pa_GetStreamCpuLoad( PaStream* stream );</div>
          
          
          返回值是浮点数，从 0.0 到 1.0 （即 0% 到 100%），这个函数对阻塞式输入输出流无效，只针对回调函数机制的音频流。在作者主机测试时，负载只有 0.0153963，约为 1.5%，PA 库占用的 CPU 资源其实很少。<br>
          <br>另外 PA 库还提供了根据采样点数据格式获取字节数的函数：<br>
          <div class="code">PaError Pa_GetSampleSize( PaSampleFormat format ) </div>
          
          比如 paUInt8 格式对应 1 字节，paFloat32 格式对应 4 字节。如果格式不支持，那么返回负数 paSampleFormatNotSupported 。<br>PA 库还提供了一个睡眠函数：<br>
           <div class="code">void Pa_Sleep( long msec ) </div>
          
          参数是毫秒时间，实际睡眠的时间可能比参数时间长一点，具体依赖操作系统相应的库函数特性。<br><br>
          关于 PA 库常用的知识就介绍到这，其他内容比如阻塞式读写的使用方法请参考 PA 库官方网站文档：<br>
          <a href="http://portaudio.com/docs/v19-doxydocs/api_overview.html" target="new">
            http://portaudio.com/docs/v19-doxydocs/api_overview.html
          </a>
          <br>PA 库源代码包中也有阻塞式读写的示例程序：
          patest_read_record.c （在 test 文件夹，阻塞式音频输入示例）、
          paex_write_sine.c（在 examples 文件夹，阻塞式音频输出示例）、
          paex_read_write_wire.c（在 examples 文件夹，边采边播示例）。
          
          <br><br>下面开始本小节 PA 库复杂接口示例，打开 QtCreator，新建一个 Qt Widgets Application 项目，在新建项目的向导里填写：<br>①项目名称 <b>paincomplex</b>，创建路径 E:\examples\ch03，点击下一步；<br>②套件选择里面选择全部套件，点击下一步；<br>③类信息界面先选择基类为 <b>QWidget</b>，修改类名为 <b>WidgetPAInComplex</b>，点击下一步；<br>④项目管理不修改，点击完成。<br>
          我们先打开 paincomplex.pro 文件，为项目添加 Qt 网络模块，并增加 PA 库的引用 ：<br>
  <div class="code">#-------------------------------------------------<br>#<br># Project created by QtCreator 2018-11-27T18:38:43<br>#<br>#-------------------------------------------------<br><br>QT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; += core gui <b>network</b><br><br>greaterThan(QT_MAJOR_VERSION, 4): QT += widgets<br><br>TARGET = paincomplex<br>TEMPLATE = app<br><br><br>SOURCES += main.cpp\<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; widgetpaincomplex.cpp<br><br>HEADERS&nbsp; += widgetpaincomplex.h<br><br>FORMS&nbsp;&nbsp;&nbsp; += widgetpaincomplex.ui<br><b><br>LIBS += -lportaudio</b></div>
          
          
          
          最后一句 LIBS +=&nbsp; 是增加库文件引用，-l （小写的L）是加入链接库的意思，portaudio 是 PA 库的名称，引用库不需要扩展名。因为 PA 库安装在 MinGW 库标准路径，编译器会自动找寻头文件和库文件，不需要额外指定 PA 库的路径。<br>编写 pro 文件后保存它，关闭该文件。
          我们打开 widgetpaincomplex.ui 界面文件，按照下图拖入控件：<br>
    <center> <img src="images/ch03/ch03-04-03.png" alt="ui" width="800">
    </center>
          第一行控件为标签“音频框架”、组合框 comboBoxHostAPI；<br>第二行控件为标签“音频设备”、组合框 comboBoxDevices，第一行和第二行使用一个栅格布局器排布。<br>第三行是标签“输入声道数量”、组合框 comboBoxChannels、标签“采样位宽”、组合框 comboBoxSampleSize；<br>第四行是标签“采样频率”、组合框 comboBoxSampleRate、标签“时间片帧数”、旋钮编辑框 spinBoxFramesPerBuffer，第三行和第四行使用一个栅格布局器进行排布。<br>第五行是标签“目标地址”、单行编辑器 lineEditIP、标签“目标端口”、旋钮编辑框 spinBoxPort，第五行使用水平布局器排布。<br>第六行是标签“文件路径”、单行编辑器 lineEditFile，第六行使用水平布局器排布。<br>第七行是“开始”按钮 pushButtonStart、“停止”按钮 pushButtonStop，第七行使用水平布局器排布。<br>第八行是标签“采集状态”，该标签对象名设置为 labelStatus 。<br>窗口整体使用垂直布局器排布，窗口大小 340*240 。<br>然后修改头两行组合框 comboBoxHostAPI、comboBoxDevices 和第五行端口编辑框 spinBoxPort 的 sizePolicy 属性，
          将这三个控件的“水平策略”改为 Expanding ：<br>
    <center> <img src="images/ch03/ch03-04-04.png" alt="sizepolicy">
    </center>
          <br>然后我们右键点击第一行的组合框 comboBoxHostAPI，在右键菜单选择“转到槽...”，
          为该组合框添加槽函数：<br>
    <center> <img src="images/slots/currentindexchange_int.png" alt="slot1">
    </center>
          
          为组合框 comboBoxHostAPI 添加 currentIndexChanged(int) 信号的槽函数。
          <br>接着我们依次右键点击两个按钮，为按钮添加槽函数：<br>
   <center> <img src="images/slots/buttonclicked.png" alt="slot2">
    </center>
          
          总共三个槽函数添加完成后，我们保存界面文件，关闭界面文件。
          然后打开头文件 widgetpaincomplex.h ，编辑内容如下：<br>
<div class="code"><span style=" color:#000080;">#ifndef</span><span style=" color:#c0c0c0;"> </span>WIDGETPAINCOMPLEX_H
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#define</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">WIDGETPAINCOMPLEX_H</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;QWidget&gt;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;portaudio.h&gt;</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">//PA库</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;QFile&gt;//文件</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;QUdpSocket&gt;//UDP套接字</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;QHostAddress&gt;//IP地址类</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;QElapsedTimer&gt;//计时器类</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">namespace</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">Ui</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">class</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">WidgetPAInComplex</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#008000;">//自定义回调函数声明</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">static</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">audioInCallback</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">const</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">void</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">*</span>inputBuffer<span style=" color:#000000;">,</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                       </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span>outputBuffer<span
style=" color:#000000;">,</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                       </span><span style=" color:#808000;">unsigned</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">long</span><span style=" color:#c0c0c0;"> </span>frameCount<span
style=" color:#000000;">,</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                       </span><span style=" color:#808000;">const</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">PaStreamCallbackTimeInfo</span><span
style=" color:#000000;">*</span><span style=" color:#c0c0c0;"> </span>timeInfo<span
style=" color:#000000;">,</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                       </span><span style=" color:#800080;">PaStreamCallbackFlags</span><span
style=" color:#c0c0c0;"> </span>statusFlags<span style=" color:#000000;">,</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                       </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span>userData<span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">)</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">;</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">class</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">WidgetPAInComplex</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">:</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">public</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QWidget</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000080;">Q_OBJECT</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">public</span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">explicit</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">WidgetPAInComplex</span><span
style=" color:#000000;">(</span><span style=" color:#800080;">QWidget</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span>parent<span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">0</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">~</span><span style=" font-style:italic; color:#000000;">WidgetPAInComplex</span><span
style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//声明公开变量，方便回调函数访问</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//音频流</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">PaStream</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span><span style=" color:#800000;">m_streamIn</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//输入声道数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_nChannels</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//采样位宽，比特数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_nSampleSize</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//采样频率</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_nSampleRate</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//时间片内帧数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_nFramesPerBuffer</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//套接字</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QUdpSocket</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_socket</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//文件</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QFile</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_file</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//计时器</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QElapsedTimer</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_calcTime</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//状态显示函数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">showStatus</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span>nFrames<span
style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span>nBytes<span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//根据采样位宽获取采样点数据格式</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">PaSampleFormat</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">getSampleFormat</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span>sampleSize<span
style=" color:#000000;">);</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">private</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#808000;">slots</span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">on_comboBoxHostAPI_currentIndexChanged</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span>index<span
style=" color:#000000;">);</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">on_pushButtonStart_clicked</span><span
style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">on_pushButtonStop_clicked</span><span
style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">private</span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">Ui</span><span
style=" color:#000000;">::</span><span style=" color:#800080;">WidgetPAInComplex</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//界面初始化</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">initUI</span><span
style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//录音时固定参数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">holdParas</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">bool</span><span
style=" color:#c0c0c0;"> </span>bHold<span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">};</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#endif</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">//</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">WIDGETPAINCOMPLEX_H</span></pre>
</div>
          
          该文件添加了 PortAudio 库、Qt 文件类、UDP套接字、IP地址类和计时器类的头文件引用。<br>在窗口类声明之前添加了回调函数声明，这个回调函数与之前简单接口示例的回调函数一样。<br>类声明中，添加了公有成员变量声明，有音频流 m_streamIn、输入声道数 m_nChannels、采样位宽 m_nSampleSize、采样频率 m_nSampleRate、时间片内帧数 m_nFramesPerBuffer、UDP套接字 m_socket、保存文件 m_file、计时器 m_calcTime。<br>添加了根据实时采样帧数和字节数，显示到状态标签的公开函数 showStatus()；<br>添加了根据采样位宽获取 PA 库采样点数据类型的函数 getSampleFormat() 。<br>三个私有槽函数是之前通过控件的右键菜单添加的。<br>最后添加了两个私有函数，initUI() 用于初始化界面控件内容；holdParas() 用于在录音时禁用输入控件，防止修改录音参数。<br>该头文件的内容与简单接口示例的头文件很类似，仅仅是增加了槽函数 on_comboBoxHostAPI_currentIndexChanged()，这个槽函数根据选中音频框架的变化，自动更新音频框架管理的设备，显示到设备组合框。<br><br>接下来分段编辑源文件 widgetpaincomplex.cpp 内容，
          首先编辑头文件包含、构造函数、析构函数的内容：<br>
<div class="code">
<style type="text/css">
p, li { white-space: pre-wrap; }
</style>

<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">"widgetpaincomplex.h"</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">"ui_widgetpaincomplex.h"</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;QDebug&gt;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000080;">#include</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">&lt;QMessageBox&gt;</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#800080;">WidgetPAInComplex</span><span style=" color:#000000;">::</span><span
style=" color:#000000;">WidgetPAInComplex</span><span style=" color:#000000;">(</span><span
style=" color:#800080;">QWidget</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">*</span><span style=" color:#000000;">parent</span><span
style=" color:#000000;">)</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QWidget</span><span
style=" color:#000000;">(</span><span style=" color:#000000;">parent</span><span
style=" color:#000000;">),</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">new</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">Ui</span><span style=" color:#000000;">::</span><span style=" color:#800080;">WidgetPAInComplex</span><span
style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setupUi</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">this</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//指针初始化为空</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_streamIn</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">NULL</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//先初始化</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">PA</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">库</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">Pa_Initialize</span><span
style=" color:#000000;">();</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//调用初始化界面函数，音频框架和设备的组合框需要用</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">PA</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">库的函数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">initUI</span><span
style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#800080;">WidgetPAInComplex</span><span style=" color:#000000;">::~</span><span
style=" font-style:italic; color:#000000;">WidgetPAInComplex</span><span style=" color:#000000;">()</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//关闭文件和套接字</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_file</span><span
style=" color:#000000;">.</span><span style=" font-style:italic; color:#000000;">close</span><span
style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_socket</span><span
style=" color:#000000;">.</span><span style=" font-style:italic; color:#000000;">close</span><span
style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//指针置空</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_streamIn</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">NULL</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//终止</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">PA</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">库引用</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">Pa_Terminate</span><span
style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//销毁窗口</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">delete</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre></div>

    添加了打印调试信息类和消息框的头文件包含。<br>在构造函数里，将流句柄 m_streamIn 设置为 NULL；<br>先调用 PA 库初始化函数 Pa_Initialize()，后调用界面初始化函数 initUI()，因为界面初始化的时候需要用到 PA 库枚举音频框架等函数。<br>析构函数将文件和套接字关闭，将流句柄 m_streamIn 设置为 NULL；<br>调用 Pa_Terminate() 终止 PA 库引用，然后销毁窗口。<br>
          <br>初始化界面函数的内容如下：<br>
 <div class="code">
<style type="text/css">
p, li { white-space: pre-wrap; }
</style>

<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#008000;">//初始化界面</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">void</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">WidgetPAInComplex</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">initUI</span><span
style=" color:#000000;">()</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//获取音频框架</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nAPICount</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">Pa_GetHostApiCount</span><span style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QString</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strTemp</span><span
style=" color:#000000;">;</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//用于构造音频框架字符串</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">for</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">i</span><span style=" color:#000000;">=</span><span style=" color:#000080;">0</span><span
style=" color:#000000;">;</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">i</span><span
style=" color:#000000;">&lt;</span><span style=" color:#000000;">nAPICount</span><span
style=" color:#000000;">;</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">i</span><span
style=" color:#000000;">++)</span><span style=" color:#008000;">//逐个添加框架名称到组合框</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">const</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">PaHostApiInfo</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span><span style=" color:#000000;">pAPIInfo</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">Pa_GetHostApiInfo</span><span style=" color:#000000;">(</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">i</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#000000;">strTemp</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">QString</span><span style=" color:#000000;">::</span><span
style=" color:#000000;">fromLocal8Bit</span><span style=" color:#000000;">(</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">pAPIInfo</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">name</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxHostAPI</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">addItem</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strTemp</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//添加头一个音频框架时触发该组合框序号变化信号</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//该信号的槽函数自动添加音频框架管理的设备</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//声道数量</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QStringList</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">listChannels</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">listChannels</span><span
style=" color:#000000;">&lt;&lt;</span><span style=" color:#008000;">"1"</span><span
style=" color:#000000;">&lt;&lt;</span><span style=" color:#008000;">"2"</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxChannels</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">addItems</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">listChannels</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//采样位宽，默认用</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">uint8，int16，int24，float32</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QStringList</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">listSampleSizes</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">listSampleSizes</span><span
style=" color:#000000;">&lt;&lt;</span><span style=" color:#008000;">"8"</span><span
style=" color:#000000;">&lt;&lt;</span><span style=" color:#008000;">"16"</span><span
style=" color:#000000;">&lt;&lt;</span><span style=" color:#008000;">"24"</span><span
style=" color:#000000;">&lt;&lt;</span><span style=" color:#008000;">"32"</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxSampleSize</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">addItems</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">listSampleSizes</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//默认用16bit采样</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxSampleSize</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setCurrentText</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">"16"</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//采样频率</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QStringList</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">listSampleRates</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">listSampleRates</span><span
style=" color:#000000;">&lt;&lt;</span><span style=" color:#008000;">"8000"</span><span
style=" color:#000000;">&lt;&lt;</span><span style=" color:#008000;">"22050"</span><span
style=" color:#000000;">&lt;&lt;</span><span style=" color:#008000;">"44100"</span><span
style=" color:#000000;">&lt;&lt;</span><span style=" color:#008000;">"48000"</span><span
style=" color:#000000;">&lt;&lt;</span><span style=" color:#008000;">"96000"</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxSampleRate</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">addItems</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">listSampleRates</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//时间片帧数范围，8k采样一毫秒8帧，96k采样一秒96000帧</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">spinBoxFramesPerBuffer</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setRange</span><span
style=" color:#000000;">(</span><span style=" color:#000080;">8</span><span style=" color:#000000;">,</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">96000</span><span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//默认</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">8k</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">采样</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">20</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">毫秒，就是</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">160</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">帧</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">spinBoxFramesPerBuffer</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setValue</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000080;">160</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//默认IP地址</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">lineEditIP</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setText</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">"127.0.0.1"</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//端口号范围</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">spinBoxPort</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setRange</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000080;">1</span><span
style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000080;">65535</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">spinBoxPort</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setValue</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000080;">12345</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">//默认端口</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//默认文件名</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">lineEditFile</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setText</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">"E:/pacomplex_8k1c16bit.pcm"</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//界面设置完毕</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">return</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre></div>
 
          
          该函数获取音频框架的计数 nAPICount；<br>然后逐一获取音频框架信息指针 pAPIInfo，根据音频框架的名称构造字符串；<br>
    将名称字符串显示到组合框 comboBoxHostAPI 。<br>comboBoxHostAPI 组合框原本没有条目，添加第一个条目时，自动触发组合框的 currentIndexChanged(int)信号，该信号的槽函数自动被执行，槽函数会自动枚举音频框架管理的设备，添加到设备组合框。<br><br>然后定义声道数量字符串列表，添加单声道、双声道字符串到字符串列表，为声道组合框 comboBoxChannels 添加多个条目。<br>定义采样位宽字符串列表，添加从 8 bit到 32bit 位宽的字符串到字符串列表，为采样位宽组合框 comboBoxSampleSize 添加多个条目，并设置默认位宽为 16bit。<br>定义采样频率字符串列表，添加从 8k 到 96k 的常用采样频率字符串到字符串列表，为采样频率组合框 comboBoxSampleRate 添加多个条目。<br>设置时间片帧数 spinBoxFramesPerBuffer 范围从 8 帧（8kHz 1ms 时间片）到 96000 帧（96kHz 1s 时间片），设置默认帧数为 160 帧（8kHz 20ms 时间片）。<br><br>设置默认 IP 为本地地址 "127.0.0.1"；设置端口号范围 1 到 65535 ，默认端口 12345 ，设置默认文件名 "E:/pacomplex_8k1c16bit.pcm" 。<br>设置界面完成后返回。<br><br>与简单接口示例相比，初始化界面函数主要多了枚举音频框架的代码，
          而枚举框架管理的音频设备代码，见下面的槽函数：<br>
<div class="code">
<style type="text/css">
p, li { white-space: pre-wrap; }
</style>

<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#008000;">//自动根据音频框架的变化，更新框架管理的设备</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">void</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">WidgetPAInComplex</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">on_comboBoxHostAPI_currentIndexChanged</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">index</span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">if</span><span
style=" color:#000000;">(</span><span style=" color:#000000;">index</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">&lt;</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">0</span><span style=" color:#000000;">)</span><span style=" color:#c0c0c0;">   </span><span
style=" color:#808000;">return</span><span style=" color:#000000;">;</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//音频框架序号不合法</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//清空旧设备</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxDevices</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">clear</span><span
style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//获取当前音频框架</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">const</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">PaHostApiInfo</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span><span style=" color:#000000;">pAPIInfo</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">Pa_GetHostApiInfo</span><span style=" color:#000000;">(</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">index</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nAPIDeviceCount</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">pAPIInfo</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#800000;">deviceCount</span><span style=" color:#000000;">;</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//框架管理的设备计数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QString</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strTemp</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//添加该音频框架管理的设备到组合框</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">for</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">i</span><span style=" color:#000000;">=</span><span style=" color:#000080;">0</span><span
style=" color:#000000;">;</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">i</span><span
style=" color:#000000;">&lt;</span><span style=" color:#000000;">nAPIDeviceCount</span><span
style=" color:#000000;">;</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">i</span><span
style=" color:#000000;">++)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#008000;">//根据设备相对序号获取绝对序号，index是框架序号，i</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">是框架设备相对序号</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nGlobali</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">Pa_HostApiDeviceIndexToDeviceIndex</span><span style=" color:#000000;">(</span><span
style=" color:#000000;">index</span><span style=" color:#000000;">,</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">i</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#008000;">//获取设备信息</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">const</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">PaDeviceInfo</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span><span style=" color:#000000;">pDevInfo</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">Pa_GetDeviceInfo</span><span style=" color:#000000;">(</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nGlobali</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#008000;">//Windows设备名称字符串是本土的</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">GBK</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">编码，需要转换一下</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#000000;">strTemp</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">QString</span><span style=" color:#000000;">::</span><span
style=" color:#000000;">fromLocal8Bit</span><span style=" color:#000000;">(</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">pDevInfo</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">name</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxDevices</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">addItem</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strTemp</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre></div>
          
          
          
          该函数先判断序号 index 是否合法，不合法直接返回；如果合法就继续后面代码。<br>当框架组合框的序号变化时，先清空旧框架管理的设备列表；<br>然后根据选中框架序号，获取音频设备信息的指针 pAPIInfo ；<br>获取该框架管理的设备计数 nAPIDeviceCount ；<br>逐一枚举框架管理的设备，根据框架序号 index 和设备相对序号 i，获取设备全局的绝对序号 nGlobali ；<br>根据设备绝对序号 nGlobali  获取设备信息指针 pDevInfo ；<br>将本地化设备名称字符串转为 Qt 字符串 strTemp ；<br>添加设备名称字符串到组合框 comboBoxDevices 。<br>
          <br>下面编写回调函数的代码：<br>
<div class="code">
<style type="text/css">
p, li { white-space: pre-wrap; }
</style>

<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#008000;">//先编写回调函数，用户数据保存窗口类对象的this指针</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">static</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">audioInCallback</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">const</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">void</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">*</span><span style=" color:#000000;">inputBuffer</span><span
style=" color:#000000;">,</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                       </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span><span style=" color:#000000;">outputBuffer</span><span
style=" color:#000000;">,</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                       </span><span style=" color:#808000;">unsigned</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">long</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">frameCount</span><span style=" color:#000000;">,</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                       </span><span style=" color:#808000;">const</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">PaStreamCallbackTimeInfo</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span><span style=" color:#000000;">timeInfo</span><span
style=" color:#000000;">,</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                       </span><span style=" color:#800080;">PaStreamCallbackFlags</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">statusFlags</span><span
style=" color:#000000;">,</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                       </span><span style=" color:#808000;">void</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span><span style=" color:#000000;">userData</span><span
style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//采集的数据，保存文件和发送网络只论字节数，不管数据格式</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">const</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">char</span><span style=" color:#000000;">*</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">dataIn</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">(</span><span style=" color:#808000;">const</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">char</span><span style=" color:#000000;">*)</span><span
style=" color:#000000;">inputBuffer</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//窗口指针</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">WidgetPAInComplex</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span><span style=" color:#000000;">pWnd</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">(</span><span style=" color:#800080;">WidgetPAInComplex</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*)</span><span style=" color:#000000;">userData</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//qint64</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">nsBegin</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">pWnd-&gt;m_calcTime.nsecsElapsed();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//计算数据字节数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nChannels</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">pWnd</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#800000;">m_nChannels</span><span style=" color:#000000;">;</span><span
style=" color:#008000;">//通道数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nBytesPerSample</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">(</span><span style=" color:#000000;">pWnd</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#800000;">m_nSampleSize</span><span style=" color:#000000;">)</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">/</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">8</span><span style=" color:#000000;">;</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">//样本字节数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nAllBytes</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">frameCount</span><span style=" color:#000000;">*</span><span
style=" color:#000000;">nChannels</span><span style=" color:#000000;">*</span><span
style=" color:#000000;">nBytesPerSample</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//写入文件</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">(</span><span style=" color:#000000;">pWnd</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">m_file</span><span
style=" color:#000000;">).</span><span style=" color:#000000;">write</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">dataIn</span><span
style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nAllBytes</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//写入套接字</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">(</span><span style=" color:#000000;">pWnd</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">m_socket</span><span
style=" color:#000000;">).</span><span style=" color:#000000;">write</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">dataIn</span><span
style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nAllBytes</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//调用状态显示函数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">pWnd</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">showStatus</span><span
style=" color:#000000;">(</span><span style=" color:#000000;">frameCount</span><span
style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nAllBytes</span><span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//qint64</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">nsEnd</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">pWnd-&gt;m_calcTime.nsecsElapsed();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//qDebug()&lt;&lt;"one</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">call</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">ns:</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">"&lt;&lt;nsEnd</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">-</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">nsBegin;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//回调函数一定要有返回值</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">return</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">paContinue</span><span
style=" color:#000000;">;</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//继续采集</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre></div>
          
          
          
          该回调函数的内容与简单接口示例的回调函数一模一样。<br>获取输入数据指针和字节数，然后写入文件和套接字，显示采集的帧数和字节数到窗口的状态标签。<br>注释的三行代码用于测试回调函数执行时间，作者实测一次回调函数耗时大约 0.1 ms 。<br>回调函数末尾一定要有返回值，通常都是返回 paContinue，表示继续采集。<br>
          <br>接下来编辑显示采集状态字符串的函数：<br>
<div class="code">
<style type="text/css">
p, li { white-space: pre-wrap; }
</style>

<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#008000;">//设置状态字符串</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">void</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">WidgetPAInComplex</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">showStatus</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">nFrames</span><span style=" color:#000000;">,</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">nBytes</span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QString</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strStatus</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">qint64</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">msCount</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800000;">m_calcTime</span><span style=" color:#000000;">.</span><span
style=" color:#000000;">elapsed</span><span style=" color:#000000;">();</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//毫秒计数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//构造字符串</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">strStatus</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span style=" color:#008000;">"%1.%2</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">s,</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">%3</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">frames,</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">%4</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">bytes"</span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">            </span><span style=" color:#000000;">.</span><span
style=" color:#000000;">arg</span><span style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">msCount</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">/</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000080;">1000</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">            </span><span style=" color:#000000;">.</span><span
style=" color:#000000;">arg</span><span style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">msCount</span><span style=" color:#000000;">%</span><span
style=" color:#000080;">1000</span><span style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">3</span><span style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">10</span><span style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">QChar</span><span style=" color:#000000;">(</span><span
style=" color:#008000;">'0'</span><span style=" color:#000000;">)</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">            </span><span style=" color:#000000;">.</span><span
style=" color:#000000;">arg</span><span style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">nFrames</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">            </span><span style=" color:#000000;">.</span><span
style=" color:#000000;">arg</span><span style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">nBytes</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">labelStatus</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setText</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strStatus</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span><span style=" color:#008000;">//显示到状态标签</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">return</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre></div>
          
          该函数获取计时器的毫秒计时，根据当前采样时间、采样帧数、字节数构造字符串，并显示到窗口的状态标签。<br>
          <br>接下来编辑 根据采样位宽获取 PA 库采样点数据类型的函数：<br>
<div class="code">
<style type="text/css">
p, li { white-space: pre-wrap; }
</style>

<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#008000;">//根据采样位宽获取采样点数据格式</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#800080;">PaSampleFormat</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800080;">WidgetPAInComplex</span><span style=" color:#000000;">::</span><span
style=" color:#000000;">getSampleFormat</span><span style=" color:#000000;">(</span><span
style=" color:#808000;">int</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">sampleSize</span><span
style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">switch</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">(</span><span style=" color:#000000;">sampleSize</span><span
style=" color:#000000;">)</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">case</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">8</span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">return</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">paUInt8</span><span
style=" color:#000000;">;</span><span style=" color:#008000;">//8位无符号整数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">break</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">case</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">16</span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">return</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">paInt16</span><span
style=" color:#000000;">;</span><span style=" color:#008000;">//16位有符号整数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">break</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">case</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">24</span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">return</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">paInt24</span><span
style=" color:#000000;">;</span><span style=" color:#008000;">//24位有符号整数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">break</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">case</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">32</span><span style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">return</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">paFloat32</span><span
style=" color:#000000;">;</span><span style=" color:#008000;">//32位浮点数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">break</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">default</span><span
style=" color:#000000;">:</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">return</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">paInt16</span><span
style=" color:#000000;">;</span><span style=" color:#008000;">//默认16位有符号整数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">break</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre></div>
          
          
          
          该函数只列举了几个常见类型：采样位宽 8 bit 对应无符号整数，16 bit对应有符号整数，24 bit对应有符号整数，32bit 对应浮点数。<br>
          <br>下面编辑“开始”按钮的槽函数代码：<br>
<div class="code">
<style type="text/css">
p, li { white-space: pre-wrap; }
</style>

<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">void</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">WidgetPAInComplex</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">on_pushButtonStart_clicked</span><span
style=" color:#000000;">()</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//获取音频框架序号</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nAPIIndex</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800000;">ui</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#800000;">comboBoxHostAPI</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#000000;">currentIndex</span><span style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//设备相对序号</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nAPIDevIndex</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800000;">ui</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#800000;">comboBoxDevices</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#000000;">currentIndex</span><span style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//转为绝对序号</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nGlobalDevIndex</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">Pa_HostApiDeviceIndexToDeviceIndex</span><span style=" color:#000000;">(</span><span
style=" color:#000000;">nAPIIndex</span><span style=" color:#000000;">,</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nAPIDevIndex</span><span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//设备信息</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">const</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800080;">PaDeviceInfo</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*</span><span style=" color:#000000;">pDevInfo</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">Pa_GetDeviceInfo</span><span style=" color:#000000;">(</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nGlobalDevIndex</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//输入声道上限</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">int</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nMaxChannels</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">pDevInfo</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#800000;">maxInputChannels</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//设置的输入声道数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_nChannels</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800000;">ui</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#800000;">comboBoxChannels</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#000000;">currentText</span><span style=" color:#000000;">().</span><span
style=" color:#000000;">toInt</span><span style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QString</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strTemp</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">if</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_nChannels</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">&gt;</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">nMaxChannels</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">)</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//超出限制</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#000000;">strTemp</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span style=" color:#008000;">"输入声道数超出设备支持上限，设置数：%1，上限数：%2"</span><span
style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                </span><span style=" color:#000000;">.</span><span
style=" color:#000000;">arg</span><span style=" color:#000000;">(</span><span style=" color:#800000;">m_nChannels</span><span
style=" color:#000000;">).</span><span style=" color:#000000;">arg</span><span style=" color:#000000;">(</span><span
style=" color:#000000;">nMaxChannels</span><span style=" color:#000000;">)</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800080;">QMessageBox</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">warning</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">this</span><span style=" color:#000000;">,</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span
style=" color:#008000;">"声道数不支持"</span><span style=" color:#000000;">),</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strTemp</span><span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">return</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//尝试打开文件</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_file</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">setFileName</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">lineEditFile</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">text</span><span
style=" color:#000000;">()</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">if</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">!</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_file</span><span
style=" color:#000000;">.</span><span style=" font-style:italic; color:#000000;">open</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QIODevice</span><span
style=" color:#000000;">::</span><span style=" color:#800080;">WriteOnly</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">)</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800080;">QMessageBox</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">warning</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">this</span><span style=" color:#000000;">,</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span
style=" color:#008000;">"打开文件"</span><span style=" color:#000000;">),</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span
style=" color:#008000;">"打开文件失败，请检查文件名和权限。"</span><span style=" color:#000000;">));</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">return</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//尝试转换字符串为IP地址对象</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QHostAddress</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">ipAddr</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">if</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">!</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">ipAddr</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">setAddress</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">lineEditIP</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">text</span><span
style=" color:#000000;">()</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">)</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800080;">QMessageBox</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">warning</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">this</span><span style=" color:#000000;">,</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span
style=" color:#008000;">"IP地址"</span><span style=" color:#000000;">),</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span
style=" color:#008000;">"IP地址不合法。"</span><span style=" color:#000000;">));</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">m_file</span><span
style=" color:#000000;">.</span><span style=" font-style:italic; color:#000000;">close</span><span
style=" color:#000000;">();</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//文件释放</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">return</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">quint16</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nPort</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800000;">ui</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#800000;">spinBoxPort</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#000000;">value</span><span style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//设置</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">UDP</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">套接字的目标地址和端口</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_socket</span><span
style=" color:#000000;">.</span><span style=" font-style:italic; color:#000000;">connectToHost</span><span
style=" color:#000000;">(</span><span style=" color:#000000;">ipAddr</span><span
style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">nPort</span><span
style=" color:#000000;">);</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//获取界面的录音参数，通道数已判断</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_nSampleSize</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800000;">ui</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#800000;">comboBoxSampleSize</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#000000;">currentText</span><span style=" color:#000000;">().</span><span
style=" color:#000000;">toInt</span><span style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_nSampleRate</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800000;">ui</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#800000;">comboBoxSampleRate</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#000000;">currentText</span><span style=" color:#000000;">().</span><span
style=" color:#000000;">toInt</span><span style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_nFramesPerBuffer</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800000;">ui</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#800000;">spinBoxFramesPerBuffer</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#000000;">value</span><span style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//时间片计算，浮点数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">double</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">dblSpan</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#808000;">double</span><span style=" color:#000000;">(</span><span
style=" color:#800000;">m_nFramesPerBuffer</span><span style=" color:#000000;">)</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">/</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#808000;">double</span><span style=" color:#000000;">(</span><span
style=" color:#800000;">m_nSampleRate</span><span style=" color:#000000;">);</span></pre>
<pre style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//定义流输入参数结构体，不需要输出参数结构体</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">PaStreamParameters</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">sinParas</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">memset</span><span
style=" color:#000000;">(&amp;</span><span style=" color:#000000;">sinParas</span><span
style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000080;">0</span><span
style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span style=" color:#808000;">sizeof</span><span
style=" color:#000000;">(</span><span style=" color:#000000;">sinParas</span><span
style=" color:#000000;">));</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//初始化为0</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//设置结构体成员</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">sinParas</span><span
style=" color:#000000;">.</span><span style=" color:#800000;">device</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">nGlobalDevIndex</span><span style=" color:#000000;">;</span><span
style=" color:#008000;">//设备绝对序号</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#008000;">nGlobalDevIndex</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">sinParas</span><span
style=" color:#000000;">.</span><span style=" color:#800000;">channelCount</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800000;">m_nChannels</span><span style=" color:#000000;">;</span><span
style=" color:#008000;">//通道数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">sinParas</span><span
style=" color:#000000;">.</span><span style=" color:#800000;">sampleFormat</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">getSampleFormat</span><span style=" color:#000000;">(</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_nSampleSize</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span><span style=" color:#008000;">//采样点数据类型</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">sinParas</span><span
style=" color:#000000;">.</span><span style=" color:#800000;">suggestedLatency</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">dblSpan</span><span style=" color:#000000;">;</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//仅为建议值，实际值可能是时间片的几倍</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">sinParas</span><span
style=" color:#000000;">.</span><span style=" color:#800000;">hostApiSpecificStreamInfo</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">NULL</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//判断格式是否支持</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">PaError</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">err</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">Pa_IsFormatSupported</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">&amp;</span><span
style=" color:#000000;">sinParas</span><span style=" color:#000000;">,</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">NULL</span><span style=" color:#000000;">,</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_nSampleRate</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">if</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000080;">paFormatIsSupported</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">!=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">err</span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#000000;">strTemp</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span style=" color:#008000;">"Pa_IsFormatSupported</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">error:</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">%1"</span><span style=" color:#000000;">).</span><span
style=" color:#000000;">arg</span><span style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">Pa_GetErrorText</span><span style=" color:#000000;">(</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">err</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">)</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800080;">QMessageBox</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">warning</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">this</span><span style=" color:#000000;">,</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span
style=" color:#008000;">"Pa_IsFormatSupported"</span><span style=" color:#000000;">),</span><span
style=" color:#000000;">strTemp</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">m_file</span><span
style=" color:#000000;">.</span><span style=" font-style:italic; color:#000000;">close</span><span
style=" color:#000000;">();</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//文件释放</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">m_socket</span><span
style=" color:#000000;">.</span><span style=" font-style:italic; color:#000000;">disconnectFromHost</span><span
style=" color:#000000;">();</span><span style=" color:#008000;">//断开</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">return</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//打开流</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">err</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">Pa_OpenStream</span><span style=" color:#000000;">(</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">&amp;</span><span
style=" color:#800000;">m_streamIn</span><span style=" color:#000000;">,</span><span
style=" color:#c0c0c0;">   </span><span style=" color:#008000;">//指向流句柄</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                         </span><span style=" color:#000000;">&amp;</span><span
style=" color:#000000;">sinParas</span><span style=" color:#000000;">,</span><span
style=" color:#c0c0c0;">     </span><span style=" color:#008000;">//输入流参数指针</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                         </span><span style=" color:#000080;">NULL</span><span
style=" color:#000000;">,</span><span style=" color:#c0c0c0;">          </span><span
style=" color:#008000;">//没有输出</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                         </span><span style=" color:#800000;">m_nSampleRate</span><span
style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//采样频率</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                         </span><span style=" color:#800000;">m_nFramesPerBuffer</span><span
style=" color:#000000;">,</span><span style=" color:#008000;">//缓冲区帧数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                         </span><span style=" color:#000080;">paNoFlag</span><span
style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//默认无标志</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                         </span>audioInCallback<span style=" color:#000000;">,</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//回调函数名称</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">                         </span><span style=" color:#000000;">(</span><span
style=" color:#808000;">void</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">*)</span><span
style=" color:#808000;">this</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span><span
style=" color:#c0c0c0;">  </span><span style=" color:#008000;">//窗口对象指针</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//判断</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">if</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">paNoError</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">!=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">err</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#000000;">strTemp</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span style=" color:#008000;">"Pa_OpenStream</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">error:</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">%1"</span><span style=" color:#000000;">).</span><span
style=" color:#000000;">arg</span><span style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">Pa_GetErrorText</span><span style=" color:#000000;">(</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">err</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">)</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800080;">QMessageBox</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">warning</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">this</span><span style=" color:#000000;">,</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span
style=" color:#008000;">"Pa_OpenStream"</span><span style=" color:#000000;">),</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strTemp</span><span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">m_file</span><span
style=" color:#000000;">.</span><span style=" font-style:italic; color:#000000;">close</span><span
style=" color:#000000;">();</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//文件释放</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">m_socket</span><span
style=" color:#000000;">.</span><span style=" font-style:italic; color:#000000;">disconnectFromHost</span><span
style=" color:#000000;">();</span><span style=" color:#008000;">//断开</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">return</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//开始流</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">err</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">Pa_StartStream</span><span style=" color:#000000;">(</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_streamIn</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">if</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">paNoError</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">!=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">err</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#000000;">strTemp</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span style=" color:#008000;">"Pa_StartStream</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">error:</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">%1"</span><span style=" color:#000000;">).</span><span
style=" color:#000000;">arg</span><span style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">Pa_GetErrorText</span><span style=" color:#000000;">(</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">err</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">)</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800080;">QMessageBox</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">warning</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">this</span><span style=" color:#000000;">,</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span
style=" color:#008000;">"Pa_StartStream"</span><span style=" color:#000000;">),</span><span
style=" color:#000000;">strTemp</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">m_file</span><span
style=" color:#000000;">.</span><span style=" font-style:italic; color:#000000;">close</span><span
style=" color:#000000;">();</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//文件释放</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800000;">m_socket</span><span
style=" color:#000000;">.</span><span style=" font-style:italic; color:#000000;">disconnectFromHost</span><span
style=" color:#000000;">();</span><span style=" color:#008000;">//断开</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">return</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_calcTime</span><span
style=" color:#000000;">.</span><span style=" color:#000000;">start</span><span
style=" color:#000000;">();</span><span style=" color:#c0c0c0;"> </span><span style=" color:#008000;">//计时开始</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//禁用输入控件，固定参数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">holdParas</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">true</span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre></div>
          
          
          
          该函数先获取音频框架序号 nAPIIndex、框架管理的设备相对序号 nAPIDevIndex，然后将设备相对序号转为绝对序号 nGlobalDevIndex；<br>根据设备绝对序号获取设备信息对象指针 pDevInfo；<br>获取设备支持的输入声道上限 nMaxChannels；<br>从窗口获取用户设置的输入声道数 m_nChannels；<br>将设置声道数与支持的上限数比较，如果设置数大于上限数，弹出消息框提示声道数量不支持，并返回；<br>如果设置的声道数能够支持，那么继续后面代码。<br><br>设置保存文件名给对象 m_file，尝试打开指定的文件名，如果打开失败，弹出消息框提示打开失败，并返回；<br>如果文件打开成功，继续后面代码。<br>定义 IP 地址对象 ipAddr，尝试将地址字符串设置给该对象，如果设置失败，那么弹窗显示 IP 地址不合法，返回；如果地址字符串合法，那么继续后面代码。<br>获取端口号 nPort，调用套接字连接目标主机函数，为 UDP 套接字 m_socket 设置目标地址和端口。<br><br>从窗口控件获取采样位宽、采样频率、时间片帧数等参数；<br>计算时间片的数值 dblSpan；<br>定义输入参数结构体对象 sinParas，并将 sinParas 整体初始化为 0；<br>填充结构体对象，设置设备全局序号 device、通道数量 channelCount、采样格式 sampleFormat 、建议延迟数值 suggestedLatency，框架定制信息 hostApiSpecificStreamInfo 一般不用不到，设为 NULL。<br>然后调用 Pa_IsFormatSupported() 函数判断输入参数 sinParas 和采样率 m_nSampleRate 是否受指定设备的支持，因为不使用输出声道，输出参数为 NULL。<br>判断该函数返回值，如果格式不支持，弹窗显示格式不支持的错误信息，关闭文件，断开连接，返回。 <br>如果输入参数 sinParas 和采样率 m_nSampleRate 能够支持，继续后面代码。<br><br>调用 Pa_OpenStream() 打开音频流，参数分别为：指向流句柄的指针 &amp;m_streamIn、输入流参数指针 &amp;sinParas、输出流参数 NULL、采样频率 m_nSampleRate、缓冲区帧数 m_nFramesPerBuffer、无标志位 paNoFlag、回调函数 audioInCallback、用户数据保存窗口对象 this 指针。<br>判断该函数返回值，如果发生错误，那么弹窗显示错误信息，关闭文件，断开连接，返回；<br>如果打开流没有错误，继续后面代码。<br><br>调用 Pa_StartStream() 开始音频流，判断返回值，如果出错，就弹窗显示错误消息，关闭文件，断开连接，返回；<br>如果开始音频流成功，那么继续后面代码。<br>开始计时器 m_calcTime；调用 holdParas(true) 固定窗口的输入控件，防止正在录音时修改录音参数。 <br><br>与简单接口示例的“开始”按钮槽函数相比，这个槽函数代码复杂一些，主要涉及音频框架、音频设备的选取和输入参数判断。复杂接口示例的灵活性更大，可以自由选择音频框架和音频设备，但也因此增加了相关的代码。<br>
          <br>接下来编辑在录音时禁用窗口输入控件的函数代码：<br>
<div class="code">
<style type="text/css">
p, li { white-space: pre-wrap; }
</style>

<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#008000;">//采集时固定参数</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">void</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">WidgetPAInComplex</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">holdParas</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">bool</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">bHold</span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxHostAPI</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setDisabled</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">bHold</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxDevices</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setDisabled</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">bHold</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxChannels</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setDisabled</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">bHold</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxSampleSize</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setDisabled</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">bHold</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">comboBoxSampleRate</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setDisabled</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">bHold</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">lineEditIP</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setDisabled</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">bHold</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">lineEditFile</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setDisabled</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">bHold</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">spinBoxFramesPerBuffer</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setDisabled</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">bHold</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">spinBoxPort</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setDisabled</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">bHold</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">ui</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#800000;">pushButtonStart</span><span
style=" color:#000000;">-&gt;</span><span style=" color:#000000;">setDisabled</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">bHold</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre></div>
          
          
          当参数为 true 时，禁用窗口的五个组合框、两个单行编辑器、两个旋钮编辑框和“开始”按钮。<br>
<div class="code">
<style type="text/css">
p, li { white-space: pre-wrap; }
</style>

<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#808000;">void</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">WidgetPAInComplex</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">on_pushButtonStop_clicked</span><span
style=" color:#000000;">()</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//判断流是否在工作</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">if</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">Pa_IsStreamActive</span><span
style=" color:#000000;">(</span><span style=" color:#800000;">m_streamIn</span><span
style=" color:#000000;">)</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">&lt;=</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000080;">0</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#008000;">//没有开始或出错，不用停止</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#808000;">return</span><span
style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">PaError</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">err</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">qint64</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">msCount</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#800000;">m_calcTime</span><span style=" color:#000000;">.</span><span
style=" color:#000000;">elapsed</span><span style=" color:#000000;">();</span><span
style=" color:#c0c0c0;">  </span><span style=" color:#008000;">//结束录音的时间</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//停止流</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">err</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">Pa_StopStream</span><span style=" color:#000000;">(</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_streamIn</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">err</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">Pa_CloseStream</span><span style=" color:#000000;">(</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#800000;">m_streamIn</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#808000;">if</span><span
style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">paNoError</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">!=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">err</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">{</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#008000;">//显示错误消息</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800080;">QString</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strErr</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span style=" color:#008000;">"PortAudio</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">error:</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">%1"</span><span style=" color:#000000;">).</span><span
style=" color:#000000;">arg</span><span style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">Pa_GetErrorText</span><span style=" color:#000000;">(</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">err</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">)</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">        </span><span style=" color:#800080;">QMessageBox</span><span
style=" color:#000000;">::</span><span style=" color:#000000;">warning</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">this</span><span style=" color:#000000;">,</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span
style=" color:#008000;">"Pa_CloseStream"</span><span style=" color:#000000;">),</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strErr</span><span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">}</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//关闭文件</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_file</span><span
style=" color:#000000;">.</span><span style=" font-style:italic; color:#000000;">close</span><span
style=" color:#000000;">();</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_socket</span><span
style=" color:#000000;">.</span><span style=" font-style:italic; color:#000000;">disconnectFromHost</span><span
style=" color:#000000;">();</span><span style=" color:#008000;">//断开</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800000;">m_streamIn</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000080;">NULL</span><span style=" color:#000000;">;</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#008000;">//恢复控件</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#000000;">holdParas</span><span
style=" color:#000000;">(</span><span style=" color:#808000;">false</span><span
style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">    </span><span style=" color:#800080;">QString</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strStatus</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">=</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">tr</span><span style=" color:#000000;">(</span><span style=" color:#008000;">"采集结束，耗时：%1.%2</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#008000;">s"</span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">           </span><span style=" color:#000000;">.</span><span
style=" color:#000000;">arg</span><span style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">msCount</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">/</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000080;">1000</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">)</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">           </span><span style=" color:#000000;">.</span><span
style=" color:#000000;">arg</span><span style=" color:#000000;">(</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">msCount</span><span style=" color:#c0c0c0;"> </span><span
style=" color:#000000;">%</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000080;">1000</span><span
style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000080;">3</span><span
style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span style=" color:#000080;">10</span><span
style=" color:#000000;">,</span><span style=" color:#c0c0c0;"> </span><span style=" color:#800080;">QChar</span><span
style=" color:#000000;">(</span><span style=" color:#008000;">'0'</span><span style=" color:#000000;">)</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">   </span><span style=" color:#008000;">//显示状态</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#c0c0c0;">   </span><span style=" color:#800000;">ui</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#800000;">labelStatus</span><span style=" color:#000000;">-&gt;</span><span
style=" color:#000000;">setText</span><span style=" color:#000000;">(</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">strStatus</span><span
style=" color:#c0c0c0;"> </span><span style=" color:#000000;">);</span></pre>
<pre style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span
style=" color:#000000;">}</span></pre></div>
          
          先判断流是否处于活跃的工作状态，如果不活跃，那么直接返回，不需要停止；<br>如果流处于活跃状态，继续后面代码。<br>获取结束录音的毫秒时间 msCount；<br>调用 Pa_StopStream( m_streamIn ) 停止流；<br>调用 Pa_CloseStream( m_streamIn ) 关闭流，释放资源；<br>检查返回值，如果出错，弹出显示错误消息。<br>关闭文件，关闭套接字，将句柄 m_streamIn 设置为 NULL。<br>调用 holdParas(false) 恢复控件；<br>从毫秒计时 msCount 提取秒数和毫秒余数，构造采集结束的信息字符串，显示到窗口状态标签。<br><br>本示例“停止”按钮的槽函数代码与之前简单接口示例的槽函数代码一样。<br><br>简单接口和复杂接口主要体现在 Pa_OpenDefaultStream() 和 Pa_OpenStream() 参数不一样，其他的步骤和代码几乎是一样的。
          <br>示例代码讲解到这，我们构建并运行本示例：<br>
  <center> <img src="images/ch03/ch03-04-05.png" alt="run1">
          </center>
          
          可以看到程序开始运行时就列举了音频框架 “MME”，音频设备 “Microsoft 声音映射器 - Input”，如果点开组合框，还可以看到其他框架以及设备。<br>点击“开始”按钮，进行录音，可以发现程序自动保存录音数据到指定文件 E:/pacomplex_8k1c16bit.pcm 。<br>点击“停止”按钮，就会停止录音。<br>
          如果我们选错了设备，将输出设备当做输入设备用，那么会弹出消息框：<br>
            <center> <img src="images/ch03/ch03-04-06.png" alt="run2">
          </center>
          输出设备的输入声道上限为 0，因此无法进行录音，我们通过检查支持的输入声道数，判断该设备不能用于音频输入。<br>在大多数情况下，输入设备只能用于输入，输出设备只能用于输出，很少有支持全双工的（即同时有输入和输出声道），一般输入流和输出流都要分开使用。<br><br>本节和本章的知识介绍到这，下一章我们开始学习 Xiph.Org 基金会的无损压缩编码 FLAC 。<br><br><br><br>
    <table style="text-align: left; width: 100%;" border="0" cellpadding="2" cellspacing="2">
      <tbody>
        <tr>
          <td style="width: 40%;">
            <div style="text-align: center;"><a href="ch03-03.htm"><img class="pic"
style="width: 32px; height: 32px;" alt="prev" src="images/pics/prev.png"></a></div>
          </td>
          <td style="width: 20%;">
            <div style="text-align: center;"><a href="contents.htm"><img class="pic"
style="width: 32px; height: 32px;" alt="contents" src="images/pics/contents.png"></a></div>
          </td>
          <td style="width: 40%;">
            <div style="text-align: center;"><a href="ch04-00.htm"><img class="pic"
style="width: 32px; height: 32px;" alt="next" src="images/pics/next.png"></a></div>
          </td>
        </tr>
      </tbody>
    </table>
</body></html>